diff --git a/transport/internet/kcp/receiving.go b/transport/internet/kcp/receiving.go index a86f24597..c6a8b6b31 100644 --- a/transport/internet/kcp/receiving.go +++ b/transport/internet/kcp/receiving.go @@ -48,3 +48,40 @@ func (this *ReceivingWindow) Advance() { this.start = 0 } } + +type ACKList struct { + timestamps []uint32 + numbers []uint32 +} + +func (this *ACKList) Add(number uint32, timestamp uint32) { + this.timestamps = append(this.timestamps, timestamp) + this.numbers = append(this.numbers, number) +} + +func (this *ACKList) Clear(una uint32) { + count := 0 + for i := 0; i < len(this.numbers); i++ { + if this.numbers[i] >= una { + if i != count { + this.numbers[count] = this.numbers[i] + this.timestamps[count] = this.timestamps[i] + } + count++ + } + } + this.numbers = this.numbers[:count] + this.timestamps = this.timestamps[:count] +} + +func (this *ACKList) AsSegment() *ACKSegment { + count := len(this.numbers) + if count > 16 { + count = 16 + } + return &ACKSegment{ + Count: byte(count), + NumberList: this.numbers[:count], + TimestampList: this.timestamps[:count], + } +} diff --git a/transport/internet/kcp/receiving_test.go b/transport/internet/kcp/receiving_test.go index bc060ce5d..3945b8594 100644 --- a/transport/internet/kcp/receiving_test.go +++ b/transport/internet/kcp/receiving_test.go @@ -34,3 +34,20 @@ func TestRecivingWindow(t *testing.T) { assert.Pointer(window.Remove(1)).Equals(seg2) assert.Pointer(window.Remove(2)).Equals(seg3) } + +func TestACKList(t *testing.T) { + assert := assert.On(t) + + ackList := new(ACKList) + ackList.Add(1, 2) + ackList.Add(3, 4) + + seg := ackList.AsSegment() + assert.Byte(seg.Count).Equals(2) + + ackList.Add(1, 3) + ackList.Clear(2) + + seg = ackList.AsSegment() + assert.Byte(seg.Count).Equals(1) +}