forked from pion/webrtc
/
payload_queue.go
101 lines (81 loc) · 2.1 KB
/
payload_queue.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package sctp
import (
"sort"
)
type payloadDataArray []*chunkPayloadData
func (s payloadDataArray) search(tsn uint32) (*chunkPayloadData, bool) {
i := sort.Search(len(s), func(i int) bool {
return s[i].tsn >= tsn
})
if i < len(s) && s[i].tsn == tsn {
return s[i], true
}
return nil, false
}
func (s payloadDataArray) sort() {
sort.Slice(s, func(i, j int) bool { return s[i].tsn < s[j].tsn })
}
type payloadQueue struct {
orderedPackets payloadDataArray
dupTSN []uint32
}
func (r *payloadQueue) pushNoCheck(p *chunkPayloadData) {
r.orderedPackets = append(r.orderedPackets, p)
r.orderedPackets.sort()
}
func (r *payloadQueue) push(p *chunkPayloadData, cumulativeTSN uint32) {
_, ok := r.orderedPackets.search(p.tsn)
// If the Data payload is already in our queue or older than our cumulativeTSN marker
if ok || p.tsn <= cumulativeTSN {
// Found the packet, log in dups
r.dupTSN = append(r.dupTSN, p.tsn)
return
}
r.orderedPackets = append(r.orderedPackets, p)
r.orderedPackets.sort()
}
func (r *payloadQueue) pop(tsn uint32) (*chunkPayloadData, bool) {
if len(r.orderedPackets) > 0 && tsn == r.orderedPackets[0].tsn {
pd := r.orderedPackets[0]
r.orderedPackets = r.orderedPackets[1:]
return pd, true
}
return nil, false
}
func (r *payloadQueue) get(tsn uint32) (*chunkPayloadData, bool) {
return r.orderedPackets.search(tsn)
}
func (r *payloadQueue) popDuplicates() []uint32 {
dups := r.dupTSN
r.dupTSN = []uint32{}
return dups
}
func (r *payloadQueue) getGapAckBlocks(cumulativeTSN uint32) (gapAckBlocks []gapAckBlock) {
var b gapAckBlock
if len(r.orderedPackets) == 0 {
return []gapAckBlock{}
}
for i, p := range r.orderedPackets {
if i == 0 {
b.start = uint16(r.orderedPackets[0].tsn - cumulativeTSN)
b.end = b.start
continue
}
diff := uint16(p.tsn - cumulativeTSN)
if b.end+1 == diff {
b.end++
} else {
gapAckBlocks = append(gapAckBlocks, gapAckBlock{
start: b.start,
end: b.end,
})
b.start = diff
b.end = diff
}
}
gapAckBlocks = append(gapAckBlocks, gapAckBlock{
start: b.start,
end: b.end,
})
return gapAckBlocks
}