redo kcp.ReceivingWindow

pull/1524/head^2
Darien Raymond 2018-07-08 12:24:37 +02:00
parent 69774c99dc
commit bbeae5be48
No known key found for this signature in database
GPG Key ID: 7251FFA14BB18169
2 changed files with 22 additions and 92 deletions

View File

@ -7,66 +7,36 @@ import (
) )
type ReceivingWindow struct { type ReceivingWindow struct {
start uint32 cache map[uint32]*DataSegment
size uint32
list []*DataSegment
} }
func NewReceivingWindow(size uint32) *ReceivingWindow { func NewReceivingWindow() *ReceivingWindow {
return &ReceivingWindow{ return &ReceivingWindow{
start: 0, cache: make(map[uint32]*DataSegment),
size: size,
list: make([]*DataSegment, size),
} }
} }
func (w *ReceivingWindow) Size() uint32 { func (w *ReceivingWindow) Set(id uint32, value *DataSegment) bool {
return w.size _, f := w.cache[id]
} if f {
func (w *ReceivingWindow) Position(idx uint32) (uint32, bool) {
if idx >= w.size {
return 0, false
}
return (w.start + idx) % w.size, true
}
func (w *ReceivingWindow) Set(idx uint32, value *DataSegment) bool {
pos, ok := w.Position(idx)
if !ok {
return false return false
} }
if w.list[pos] != nil { w.cache[id] = value
return false
}
w.list[pos] = value
return true return true
} }
func (w *ReceivingWindow) Remove(idx uint32) *DataSegment { func (w *ReceivingWindow) Has(id uint32) bool {
pos, ok := w.Position(idx) _, f := w.cache[id]
if !ok { return f
}
func (w *ReceivingWindow) Remove(id uint32) *DataSegment {
v, f := w.cache[id]
if !f {
return nil return nil
} }
e := w.list[pos] delete(w.cache, id)
w.list[pos] = nil return v
return e
}
func (w *ReceivingWindow) RemoveFirst() *DataSegment {
return w.Remove(0)
}
func (w *ReceivingWindow) HasFirst() bool {
pos, _ := w.Position(0)
return w.list[pos] != nil
}
func (w *ReceivingWindow) Advance() {
w.start++
if w.start == w.size {
w.start = 0
}
} }
type AckList struct { type AckList struct {
@ -167,15 +137,10 @@ type ReceivingWorker struct {
} }
func NewReceivingWorker(kcp *Connection) *ReceivingWorker { func NewReceivingWorker(kcp *Connection) *ReceivingWorker {
windowsSize := kcp.Config.GetReceivingInFlightSize()
if windowsSize > kcp.Config.GetReceivingBufferSize() {
windowsSize = kcp.Config.GetReceivingBufferSize()
}
worker := &ReceivingWorker{ worker := &ReceivingWorker{
conn: kcp, conn: kcp,
window: NewReceivingWindow(kcp.Config.GetReceivingBufferSize()), window: NewReceivingWindow(),
windowSize: windowsSize, windowSize: kcp.Config.GetReceivingInFlightSize(),
} }
worker.acklist = NewAckList(worker) worker.acklist = NewAckList(worker)
return worker return worker
@ -206,7 +171,7 @@ func (w *ReceivingWorker) ProcessSegment(seg *DataSegment) {
w.acklist.Clear(seg.SendingNext) w.acklist.Clear(seg.SendingNext)
w.acklist.Add(number, seg.Timestamp) w.acklist.Add(number, seg.Timestamp)
if !w.window.Set(idx, seg) { if !w.window.Set(seg.Number, seg) {
seg.Release() seg.Release()
} }
} }
@ -223,11 +188,10 @@ func (w *ReceivingWorker) ReadMultiBuffer() buf.MultiBuffer {
w.Lock() w.Lock()
defer w.Unlock() defer w.Unlock()
for { for {
seg := w.window.RemoveFirst() seg := w.window.Remove(w.nextNumber)
if seg == nil { if seg == nil {
break break
} }
w.window.Advance()
w.nextNumber++ w.nextNumber++
mb.Append(seg.Detach()) mb.Append(seg.Detach())
seg.Release() seg.Release()
@ -248,7 +212,7 @@ func (w *ReceivingWorker) Read(b []byte) int {
func (w *ReceivingWorker) IsDataAvailable() bool { func (w *ReceivingWorker) IsDataAvailable() bool {
w.RLock() w.RLock()
defer w.RUnlock() defer w.RUnlock()
return w.window.HasFirst() return w.window.Has(w.nextNumber)
} }
func (w *ReceivingWorker) NextNumber() uint32 { func (w *ReceivingWorker) NextNumber() uint32 {

View File

@ -1,34 +0,0 @@
package kcp_test
import (
"testing"
. "v2ray.com/core/transport/internet/kcp"
. "v2ray.com/ext/assert"
)
func TestRecivingWindow(t *testing.T) {
assert := With(t)
window := NewReceivingWindow(3)
seg0 := &DataSegment{}
seg1 := &DataSegment{}
seg2 := &DataSegment{}
seg3 := &DataSegment{}
assert(window.Set(0, seg0), IsTrue)
assert(window.RemoveFirst(), Equals, seg0)
e := window.RemoveFirst()
assert(e, IsNil)
assert(window.Set(1, seg1), IsTrue)
assert(window.Set(2, seg2), IsTrue)
window.Advance()
assert(window.Set(2, seg3), IsTrue)
assert(window.RemoveFirst(), Equals, seg1)
assert(window.Remove(1), Equals, seg2)
assert(window.Remove(2), Equals, seg3)
}