2016-06-25 15:35:18 -04:00
|
|
|
package kcp
|
|
|
|
|
2016-06-30 08:51:49 -04:00
|
|
|
import (
|
|
|
|
"sync"
|
|
|
|
|
2016-08-20 14:55:45 -04:00
|
|
|
"v2ray.com/core/common/alloc"
|
2016-06-30 08:51:49 -04:00
|
|
|
)
|
|
|
|
|
2016-06-25 15:35:18 -04:00
|
|
|
type ReceivingWindow struct {
|
|
|
|
start uint32
|
|
|
|
size uint32
|
2016-06-29 04:34:34 -04:00
|
|
|
list []*DataSegment
|
2016-06-25 15:35:18 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewReceivingWindow(size uint32) *ReceivingWindow {
|
|
|
|
return &ReceivingWindow{
|
|
|
|
start: 0,
|
|
|
|
size: size,
|
2016-06-29 04:34:34 -04:00
|
|
|
list: make([]*DataSegment, size),
|
2016-06-25 15:35:18 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (this *ReceivingWindow) Size() uint32 {
|
|
|
|
return this.size
|
|
|
|
}
|
|
|
|
|
|
|
|
func (this *ReceivingWindow) Position(idx uint32) uint32 {
|
|
|
|
return (idx + this.start) % this.size
|
|
|
|
}
|
|
|
|
|
2016-06-29 04:34:34 -04:00
|
|
|
func (this *ReceivingWindow) Set(idx uint32, value *DataSegment) bool {
|
2016-06-25 15:35:18 -04:00
|
|
|
pos := this.Position(idx)
|
|
|
|
if this.list[pos] != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
this.list[pos] = value
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2016-06-29 04:34:34 -04:00
|
|
|
func (this *ReceivingWindow) Remove(idx uint32) *DataSegment {
|
2016-06-25 15:35:18 -04:00
|
|
|
pos := this.Position(idx)
|
|
|
|
e := this.list[pos]
|
|
|
|
this.list[pos] = nil
|
|
|
|
return e
|
|
|
|
}
|
|
|
|
|
2016-06-29 04:34:34 -04:00
|
|
|
func (this *ReceivingWindow) RemoveFirst() *DataSegment {
|
2016-06-25 15:35:18 -04:00
|
|
|
return this.Remove(0)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (this *ReceivingWindow) Advance() {
|
|
|
|
this.start++
|
|
|
|
if this.start == this.size {
|
|
|
|
this.start = 0
|
|
|
|
}
|
|
|
|
}
|
2016-06-27 16:34:46 -04:00
|
|
|
|
2016-07-02 05:33:34 -04:00
|
|
|
type AckList struct {
|
2016-07-02 15:26:50 -04:00
|
|
|
writer SegmentWriter
|
2016-06-27 16:34:46 -04:00
|
|
|
timestamps []uint32
|
|
|
|
numbers []uint32
|
2016-06-30 16:19:30 -04:00
|
|
|
nextFlush []uint32
|
|
|
|
}
|
|
|
|
|
2016-07-02 17:18:12 -04:00
|
|
|
func NewAckList(writer SegmentWriter) *AckList {
|
2016-07-02 05:33:34 -04:00
|
|
|
return &AckList{
|
2016-07-02 15:26:50 -04:00
|
|
|
writer: writer,
|
2016-06-30 16:19:30 -04:00
|
|
|
timestamps: make([]uint32, 0, 32),
|
|
|
|
numbers: make([]uint32, 0, 32),
|
|
|
|
nextFlush: make([]uint32, 0, 32),
|
|
|
|
}
|
2016-06-27 16:34:46 -04:00
|
|
|
}
|
|
|
|
|
2016-07-02 05:33:34 -04:00
|
|
|
func (this *AckList) Add(number uint32, timestamp uint32) {
|
2016-06-27 16:34:46 -04:00
|
|
|
this.timestamps = append(this.timestamps, timestamp)
|
|
|
|
this.numbers = append(this.numbers, number)
|
2016-06-30 16:19:30 -04:00
|
|
|
this.nextFlush = append(this.nextFlush, 0)
|
2016-06-27 16:34:46 -04:00
|
|
|
}
|
|
|
|
|
2016-07-02 05:33:34 -04:00
|
|
|
func (this *AckList) Clear(una uint32) {
|
2016-06-27 16:34:46 -04:00
|
|
|
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]
|
2016-06-30 16:19:30 -04:00
|
|
|
this.nextFlush[count] = this.nextFlush[i]
|
2016-06-27 16:34:46 -04:00
|
|
|
}
|
|
|
|
count++
|
|
|
|
}
|
|
|
|
}
|
2016-06-29 17:41:04 -04:00
|
|
|
if count < len(this.numbers) {
|
|
|
|
this.numbers = this.numbers[:count]
|
|
|
|
this.timestamps = this.timestamps[:count]
|
2016-06-30 16:19:30 -04:00
|
|
|
this.nextFlush = this.nextFlush[:count]
|
2016-06-29 17:41:04 -04:00
|
|
|
}
|
2016-06-27 16:34:46 -04:00
|
|
|
}
|
|
|
|
|
2016-07-02 16:28:28 -04:00
|
|
|
func (this *AckList) Flush(current uint32, rto uint32) {
|
2016-07-05 04:28:23 -04:00
|
|
|
seg := NewAckSegment()
|
2016-07-05 04:33:11 -04:00
|
|
|
for i := 0; i < len(this.numbers) && !seg.IsFull(); i++ {
|
2016-06-30 16:19:30 -04:00
|
|
|
if this.nextFlush[i] <= current {
|
2016-08-05 14:59:33 -04:00
|
|
|
seg.PutNumber(this.numbers[i])
|
|
|
|
seg.PutTimestamp(this.timestamps[i])
|
2016-07-02 16:28:28 -04:00
|
|
|
this.nextFlush[i] = current + rto/2
|
2016-06-30 16:19:30 -04:00
|
|
|
}
|
2016-06-27 16:34:46 -04:00
|
|
|
}
|
2016-06-30 16:19:30 -04:00
|
|
|
if seg.Count > 0 {
|
2016-07-02 15:26:50 -04:00
|
|
|
this.writer.Write(seg)
|
2016-07-05 08:08:08 -04:00
|
|
|
seg.Release()
|
2016-06-30 16:19:30 -04:00
|
|
|
}
|
2016-07-02 15:26:50 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
type ReceivingWorker struct {
|
2016-07-12 11:56:36 -04:00
|
|
|
sync.RWMutex
|
2016-07-06 11:34:38 -04:00
|
|
|
conn *Connection
|
2016-08-24 17:51:53 -04:00
|
|
|
leftOver *alloc.Buffer
|
2016-07-06 11:34:38 -04:00
|
|
|
window *ReceivingWindow
|
|
|
|
acklist *AckList
|
|
|
|
updated bool
|
|
|
|
nextNumber uint32
|
|
|
|
windowSize uint32
|
2016-07-02 15:26:50 -04:00
|
|
|
}
|
|
|
|
|
2016-07-05 17:02:52 -04:00
|
|
|
func NewReceivingWorker(kcp *Connection) *ReceivingWorker {
|
2016-07-02 15:26:50 -04:00
|
|
|
worker := &ReceivingWorker{
|
2016-07-05 17:02:52 -04:00
|
|
|
conn: kcp,
|
2016-08-25 03:45:56 -04:00
|
|
|
window: NewReceivingWindow(effectiveConfig.GetReceivingBufferSize()),
|
|
|
|
windowSize: effectiveConfig.GetReceivingInFlightSize(),
|
2016-07-02 15:26:50 -04:00
|
|
|
}
|
2016-07-02 17:18:12 -04:00
|
|
|
worker.acklist = NewAckList(worker)
|
2016-07-02 15:26:50 -04:00
|
|
|
return worker
|
|
|
|
}
|
|
|
|
|
|
|
|
func (this *ReceivingWorker) ProcessSendingNext(number uint32) {
|
2016-07-06 11:34:38 -04:00
|
|
|
this.Lock()
|
|
|
|
defer this.Unlock()
|
|
|
|
|
2016-07-02 15:26:50 -04:00
|
|
|
this.acklist.Clear(number)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (this *ReceivingWorker) ProcessSegment(seg *DataSegment) {
|
2016-07-06 11:34:38 -04:00
|
|
|
this.Lock()
|
|
|
|
defer this.Unlock()
|
|
|
|
|
2016-07-02 15:26:50 -04:00
|
|
|
number := seg.Number
|
2016-07-02 18:38:33 -04:00
|
|
|
idx := number - this.nextNumber
|
|
|
|
if idx >= this.windowSize {
|
2016-07-02 15:26:50 -04:00
|
|
|
return
|
|
|
|
}
|
2016-07-06 11:34:38 -04:00
|
|
|
this.acklist.Clear(seg.SendingNext)
|
2016-07-02 15:26:50 -04:00
|
|
|
this.acklist.Add(number, seg.Timestamp)
|
|
|
|
|
|
|
|
if !this.window.Set(idx, seg) {
|
|
|
|
seg.Release()
|
|
|
|
}
|
2016-08-25 03:45:56 -04:00
|
|
|
this.updated = true
|
2016-08-24 17:51:53 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (this *ReceivingWorker) Read(b []byte) int {
|
|
|
|
this.Lock()
|
|
|
|
defer this.Unlock()
|
|
|
|
|
|
|
|
total := 0
|
|
|
|
if this.leftOver != nil {
|
|
|
|
nBytes := copy(b, this.leftOver.Value)
|
|
|
|
if nBytes < this.leftOver.Len() {
|
|
|
|
this.leftOver.SliceFrom(nBytes)
|
|
|
|
return nBytes
|
|
|
|
}
|
|
|
|
this.leftOver.Release()
|
|
|
|
this.leftOver = nil
|
|
|
|
total += nBytes
|
|
|
|
}
|
2016-07-02 15:26:50 -04:00
|
|
|
|
2016-08-24 17:51:53 -04:00
|
|
|
for total < len(b) {
|
2016-07-02 15:26:50 -04:00
|
|
|
seg := this.window.RemoveFirst()
|
|
|
|
if seg == nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
this.window.Advance()
|
|
|
|
this.nextNumber++
|
|
|
|
this.updated = true
|
|
|
|
|
2016-08-24 17:51:53 -04:00
|
|
|
nBytes := copy(b[total:], seg.Data.Value)
|
|
|
|
total += nBytes
|
|
|
|
if nBytes < seg.Data.Len() {
|
|
|
|
seg.Data.SliceFrom(nBytes)
|
|
|
|
this.leftOver = seg.Data
|
|
|
|
seg.Data = nil
|
|
|
|
seg.Release()
|
|
|
|
break
|
|
|
|
}
|
|
|
|
seg.Release()
|
|
|
|
}
|
|
|
|
return total
|
2016-07-02 15:26:50 -04:00
|
|
|
}
|
|
|
|
|
2016-07-05 17:02:52 -04:00
|
|
|
func (this *ReceivingWorker) Flush(current uint32) {
|
2016-07-06 11:34:38 -04:00
|
|
|
this.Lock()
|
|
|
|
defer this.Unlock()
|
|
|
|
|
2016-07-05 17:53:46 -04:00
|
|
|
this.acklist.Flush(current, this.conn.roundTrip.Timeout())
|
2016-07-02 15:26:50 -04:00
|
|
|
}
|
|
|
|
|
2016-07-04 08:17:42 -04:00
|
|
|
func (this *ReceivingWorker) Write(seg Segment) {
|
2016-07-02 16:17:41 -04:00
|
|
|
ackSeg := seg.(*AckSegment)
|
2016-07-05 17:02:52 -04:00
|
|
|
ackSeg.Conv = this.conn.conv
|
2016-07-02 15:26:50 -04:00
|
|
|
ackSeg.ReceivingNext = this.nextNumber
|
|
|
|
ackSeg.ReceivingWindow = this.nextNumber + this.windowSize
|
2016-07-05 17:02:52 -04:00
|
|
|
if this.conn.state == StateReadyToClose {
|
2016-07-14 16:52:00 -04:00
|
|
|
ackSeg.Option = SegmentOptionClose
|
2016-07-02 15:26:50 -04:00
|
|
|
}
|
2016-07-05 17:02:52 -04:00
|
|
|
this.conn.output.Write(ackSeg)
|
2016-07-02 15:26:50 -04:00
|
|
|
this.updated = false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (this *ReceivingWorker) CloseRead() {
|
|
|
|
}
|
|
|
|
|
|
|
|
func (this *ReceivingWorker) PingNecessary() bool {
|
2016-07-12 11:56:36 -04:00
|
|
|
this.RLock()
|
|
|
|
defer this.RUnlock()
|
2016-07-02 15:26:50 -04:00
|
|
|
return this.updated
|
2016-06-27 16:34:46 -04:00
|
|
|
}
|
2016-07-12 11:56:36 -04:00
|
|
|
|
|
|
|
func (this *ReceivingWorker) MarkPingNecessary(b bool) {
|
|
|
|
this.Lock()
|
|
|
|
defer this.Unlock()
|
|
|
|
this.updated = b
|
|
|
|
}
|