2019-02-01 19:08:21 +00:00
|
|
|
// +build !confonly
|
|
|
|
|
2016-06-25 19:35:18 +00:00
|
|
|
package kcp
|
|
|
|
|
2016-06-30 12:51:49 +00:00
|
|
|
import (
|
|
|
|
"sync"
|
|
|
|
|
2016-12-09 10:35:27 +00:00
|
|
|
"v2ray.com/core/common/buf"
|
2016-06-30 12:51:49 +00:00
|
|
|
)
|
|
|
|
|
2016-06-25 19:35:18 +00:00
|
|
|
type ReceivingWindow struct {
|
2018-07-08 10:24:37 +00:00
|
|
|
cache map[uint32]*DataSegment
|
2016-06-25 19:35:18 +00:00
|
|
|
}
|
|
|
|
|
2018-07-08 10:24:37 +00:00
|
|
|
func NewReceivingWindow() *ReceivingWindow {
|
2016-06-25 19:35:18 +00:00
|
|
|
return &ReceivingWindow{
|
2018-07-08 10:24:37 +00:00
|
|
|
cache: make(map[uint32]*DataSegment),
|
2016-06-25 19:35:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-08 10:24:37 +00:00
|
|
|
func (w *ReceivingWindow) Set(id uint32, value *DataSegment) bool {
|
|
|
|
_, f := w.cache[id]
|
|
|
|
if f {
|
2016-06-25 19:35:18 +00:00
|
|
|
return false
|
|
|
|
}
|
2018-07-08 10:24:37 +00:00
|
|
|
w.cache[id] = value
|
2016-06-25 19:35:18 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2018-07-08 10:24:37 +00:00
|
|
|
func (w *ReceivingWindow) Has(id uint32) bool {
|
|
|
|
_, f := w.cache[id]
|
|
|
|
return f
|
2017-02-17 23:04:25 +00:00
|
|
|
}
|
|
|
|
|
2018-07-08 10:24:37 +00:00
|
|
|
func (w *ReceivingWindow) Remove(id uint32) *DataSegment {
|
|
|
|
v, f := w.cache[id]
|
|
|
|
if !f {
|
|
|
|
return nil
|
2016-06-25 19:35:18 +00:00
|
|
|
}
|
2018-07-08 10:24:37 +00:00
|
|
|
delete(w.cache, id)
|
|
|
|
return v
|
2016-06-25 19:35:18 +00:00
|
|
|
}
|
2016-06-27 20:34:46 +00:00
|
|
|
|
2016-07-02 09:33:34 +00:00
|
|
|
type AckList struct {
|
2016-07-02 19:26:50 +00:00
|
|
|
writer SegmentWriter
|
2016-06-27 20:34:46 +00:00
|
|
|
timestamps []uint32
|
|
|
|
numbers []uint32
|
2016-06-30 20:19:30 +00:00
|
|
|
nextFlush []uint32
|
2016-11-28 21:06:32 +00:00
|
|
|
|
|
|
|
flushCandidates []uint32
|
2016-12-02 15:49:33 +00:00
|
|
|
dirty bool
|
2016-06-30 20:19:30 +00:00
|
|
|
}
|
|
|
|
|
2016-07-02 21:18:12 +00:00
|
|
|
func NewAckList(writer SegmentWriter) *AckList {
|
2016-07-02 09:33:34 +00:00
|
|
|
return &AckList{
|
2016-11-28 21:06:32 +00:00
|
|
|
writer: writer,
|
2016-12-02 15:49:33 +00:00
|
|
|
timestamps: make([]uint32, 0, 128),
|
|
|
|
numbers: make([]uint32, 0, 128),
|
|
|
|
nextFlush: make([]uint32, 0, 128),
|
2016-11-28 21:06:32 +00:00
|
|
|
flushCandidates: make([]uint32, 0, 128),
|
2016-06-30 20:19:30 +00:00
|
|
|
}
|
2016-06-27 20:34:46 +00:00
|
|
|
}
|
|
|
|
|
2018-01-17 16:36:14 +00:00
|
|
|
func (l *AckList) Add(number uint32, timestamp uint32) {
|
|
|
|
l.timestamps = append(l.timestamps, timestamp)
|
|
|
|
l.numbers = append(l.numbers, number)
|
|
|
|
l.nextFlush = append(l.nextFlush, 0)
|
|
|
|
l.dirty = true
|
2016-06-27 20:34:46 +00:00
|
|
|
}
|
|
|
|
|
2018-01-17 16:36:14 +00:00
|
|
|
func (l *AckList) Clear(una uint32) {
|
2016-06-27 20:34:46 +00:00
|
|
|
count := 0
|
2018-01-17 16:36:14 +00:00
|
|
|
for i := 0; i < len(l.numbers); i++ {
|
|
|
|
if l.numbers[i] < una {
|
2016-11-18 15:19:13 +00:00
|
|
|
continue
|
2016-06-27 20:34:46 +00:00
|
|
|
}
|
2016-11-18 15:19:13 +00:00
|
|
|
if i != count {
|
2018-01-17 16:36:14 +00:00
|
|
|
l.numbers[count] = l.numbers[i]
|
|
|
|
l.timestamps[count] = l.timestamps[i]
|
|
|
|
l.nextFlush[count] = l.nextFlush[i]
|
2016-11-18 15:19:13 +00:00
|
|
|
}
|
|
|
|
count++
|
2016-06-27 20:34:46 +00:00
|
|
|
}
|
2018-01-17 16:36:14 +00:00
|
|
|
if count < len(l.numbers) {
|
|
|
|
l.numbers = l.numbers[:count]
|
|
|
|
l.timestamps = l.timestamps[:count]
|
|
|
|
l.nextFlush = l.nextFlush[:count]
|
|
|
|
l.dirty = true
|
2016-06-29 21:41:04 +00:00
|
|
|
}
|
2016-06-27 20:34:46 +00:00
|
|
|
}
|
|
|
|
|
2018-01-17 16:36:14 +00:00
|
|
|
func (l *AckList) Flush(current uint32, rto uint32) {
|
|
|
|
l.flushCandidates = l.flushCandidates[:0]
|
2016-11-28 21:06:32 +00:00
|
|
|
|
2016-07-05 08:28:23 +00:00
|
|
|
seg := NewAckSegment()
|
2018-01-17 16:36:14 +00:00
|
|
|
for i := 0; i < len(l.numbers); i++ {
|
|
|
|
if l.nextFlush[i] > current {
|
|
|
|
if len(l.flushCandidates) < cap(l.flushCandidates) {
|
|
|
|
l.flushCandidates = append(l.flushCandidates, l.numbers[i])
|
2016-11-28 21:06:32 +00:00
|
|
|
}
|
2016-11-18 15:19:13 +00:00
|
|
|
continue
|
|
|
|
}
|
2018-01-17 16:36:14 +00:00
|
|
|
seg.PutNumber(l.numbers[i])
|
|
|
|
seg.PutTimestamp(l.timestamps[i])
|
2016-11-29 16:12:09 +00:00
|
|
|
timeout := rto / 2
|
2016-11-18 15:19:13 +00:00
|
|
|
if timeout < 20 {
|
|
|
|
timeout = 20
|
2016-06-30 20:19:30 +00:00
|
|
|
}
|
2018-01-17 16:36:14 +00:00
|
|
|
l.nextFlush[i] = current + timeout
|
2016-11-29 07:31:19 +00:00
|
|
|
|
|
|
|
if seg.IsFull() {
|
2018-01-17 16:36:14 +00:00
|
|
|
l.writer.Write(seg)
|
2016-11-29 07:31:19 +00:00
|
|
|
seg.Release()
|
|
|
|
seg = NewAckSegment()
|
2018-01-17 16:36:14 +00:00
|
|
|
l.dirty = false
|
2016-11-29 07:31:19 +00:00
|
|
|
}
|
2016-06-27 20:34:46 +00:00
|
|
|
}
|
2018-07-08 21:03:00 +00:00
|
|
|
|
2018-01-17 16:36:14 +00:00
|
|
|
if l.dirty || !seg.IsEmpty() {
|
|
|
|
for _, number := range l.flushCandidates {
|
2016-11-28 21:06:32 +00:00
|
|
|
if seg.IsFull() {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
seg.PutNumber(number)
|
|
|
|
}
|
2018-01-17 16:36:14 +00:00
|
|
|
l.writer.Write(seg)
|
|
|
|
l.dirty = false
|
2016-06-30 20:19:30 +00:00
|
|
|
}
|
2018-07-08 21:03:00 +00:00
|
|
|
|
|
|
|
seg.Release()
|
2016-07-02 19:26:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type ReceivingWorker struct {
|
2016-07-12 15:56:36 +00:00
|
|
|
sync.RWMutex
|
2016-07-06 15:34:38 +00:00
|
|
|
conn *Connection
|
2017-04-20 13:02:35 +00:00
|
|
|
leftOver buf.MultiBuffer
|
2016-07-06 15:34:38 +00:00
|
|
|
window *ReceivingWindow
|
|
|
|
acklist *AckList
|
|
|
|
nextNumber uint32
|
|
|
|
windowSize uint32
|
2016-07-02 19:26:50 +00:00
|
|
|
}
|
|
|
|
|
2016-07-05 21:02:52 +00:00
|
|
|
func NewReceivingWorker(kcp *Connection) *ReceivingWorker {
|
2016-07-02 19:26:50 +00:00
|
|
|
worker := &ReceivingWorker{
|
2016-07-05 21:02:52 +00:00
|
|
|
conn: kcp,
|
2018-07-08 10:24:37 +00:00
|
|
|
window: NewReceivingWindow(),
|
|
|
|
windowSize: kcp.Config.GetReceivingInFlightSize(),
|
2016-07-02 19:26:50 +00:00
|
|
|
}
|
2016-07-02 21:18:12 +00:00
|
|
|
worker.acklist = NewAckList(worker)
|
2016-07-02 19:26:50 +00:00
|
|
|
return worker
|
|
|
|
}
|
|
|
|
|
2017-12-03 13:56:00 +00:00
|
|
|
func (w *ReceivingWorker) Release() {
|
|
|
|
w.Lock()
|
2018-11-17 21:45:07 +00:00
|
|
|
buf.ReleaseMulti(w.leftOver)
|
|
|
|
w.leftOver = nil
|
2017-12-03 13:56:00 +00:00
|
|
|
w.Unlock()
|
2016-11-21 21:41:12 +00:00
|
|
|
}
|
|
|
|
|
2017-12-03 13:56:00 +00:00
|
|
|
func (w *ReceivingWorker) ProcessSendingNext(number uint32) {
|
|
|
|
w.Lock()
|
|
|
|
defer w.Unlock()
|
2016-07-06 15:34:38 +00:00
|
|
|
|
2017-12-03 13:56:00 +00:00
|
|
|
w.acklist.Clear(number)
|
2016-07-02 19:26:50 +00:00
|
|
|
}
|
|
|
|
|
2017-12-03 13:56:00 +00:00
|
|
|
func (w *ReceivingWorker) ProcessSegment(seg *DataSegment) {
|
|
|
|
w.Lock()
|
|
|
|
defer w.Unlock()
|
2016-07-06 15:34:38 +00:00
|
|
|
|
2016-07-02 19:26:50 +00:00
|
|
|
number := seg.Number
|
2017-12-03 13:56:00 +00:00
|
|
|
idx := number - w.nextNumber
|
|
|
|
if idx >= w.windowSize {
|
2016-07-02 19:26:50 +00:00
|
|
|
return
|
|
|
|
}
|
2017-12-03 13:56:00 +00:00
|
|
|
w.acklist.Clear(seg.SendingNext)
|
|
|
|
w.acklist.Add(number, seg.Timestamp)
|
2016-07-02 19:26:50 +00:00
|
|
|
|
2018-07-08 10:24:37 +00:00
|
|
|
if !w.window.Set(seg.Number, seg) {
|
2016-07-02 19:26:50 +00:00
|
|
|
seg.Release()
|
|
|
|
}
|
2016-08-24 21:51:53 +00:00
|
|
|
}
|
|
|
|
|
2017-12-03 13:56:00 +00:00
|
|
|
func (w *ReceivingWorker) ReadMultiBuffer() buf.MultiBuffer {
|
|
|
|
if w.leftOver != nil {
|
|
|
|
mb := w.leftOver
|
|
|
|
w.leftOver = nil
|
2017-04-20 13:02:35 +00:00
|
|
|
return mb
|
2016-08-24 21:51:53 +00:00
|
|
|
}
|
2016-07-02 19:26:50 +00:00
|
|
|
|
2018-11-16 10:29:16 +00:00
|
|
|
mb := make(buf.MultiBuffer, 0, 32)
|
2017-04-20 13:02:35 +00:00
|
|
|
|
2017-12-03 13:56:00 +00:00
|
|
|
w.Lock()
|
|
|
|
defer w.Unlock()
|
2017-04-20 13:02:35 +00:00
|
|
|
for {
|
2018-07-08 10:24:37 +00:00
|
|
|
seg := w.window.Remove(w.nextNumber)
|
2016-07-02 19:26:50 +00:00
|
|
|
if seg == nil {
|
|
|
|
break
|
|
|
|
}
|
2017-12-03 13:56:00 +00:00
|
|
|
w.nextNumber++
|
2018-11-17 08:12:20 +00:00
|
|
|
mb = append(mb, seg.Detach())
|
2016-08-24 21:51:53 +00:00
|
|
|
seg.Release()
|
|
|
|
}
|
2017-04-20 13:02:35 +00:00
|
|
|
|
|
|
|
return mb
|
|
|
|
}
|
|
|
|
|
2017-12-03 13:56:00 +00:00
|
|
|
func (w *ReceivingWorker) Read(b []byte) int {
|
|
|
|
mb := w.ReadMultiBuffer()
|
2018-07-29 13:10:06 +00:00
|
|
|
if mb.IsEmpty() {
|
|
|
|
return 0
|
|
|
|
}
|
2018-11-18 18:44:32 +00:00
|
|
|
mb, nBytes := buf.SplitBytes(mb, b)
|
2017-04-20 13:02:35 +00:00
|
|
|
if !mb.IsEmpty() {
|
2017-12-03 13:56:00 +00:00
|
|
|
w.leftOver = mb
|
2017-04-20 13:02:35 +00:00
|
|
|
}
|
|
|
|
return nBytes
|
2016-07-02 19:26:50 +00:00
|
|
|
}
|
|
|
|
|
2017-02-17 23:04:25 +00:00
|
|
|
func (w *ReceivingWorker) IsDataAvailable() bool {
|
|
|
|
w.RLock()
|
|
|
|
defer w.RUnlock()
|
2018-07-08 10:24:37 +00:00
|
|
|
return w.window.Has(w.nextNumber)
|
2017-02-17 23:04:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (w *ReceivingWorker) NextNumber() uint32 {
|
|
|
|
w.RLock()
|
|
|
|
defer w.RUnlock()
|
|
|
|
|
|
|
|
return w.nextNumber
|
|
|
|
}
|
|
|
|
|
2017-12-03 13:56:00 +00:00
|
|
|
func (w *ReceivingWorker) Flush(current uint32) {
|
|
|
|
w.Lock()
|
|
|
|
defer w.Unlock()
|
2016-07-06 15:34:38 +00:00
|
|
|
|
2017-12-03 13:56:00 +00:00
|
|
|
w.acklist.Flush(current, w.conn.roundTrip.Timeout())
|
2016-07-02 19:26:50 +00:00
|
|
|
}
|
|
|
|
|
2017-12-03 13:56:00 +00:00
|
|
|
func (w *ReceivingWorker) Write(seg Segment) error {
|
2016-07-02 20:17:41 +00:00
|
|
|
ackSeg := seg.(*AckSegment)
|
2017-12-14 22:24:40 +00:00
|
|
|
ackSeg.Conv = w.conn.meta.Conversation
|
2017-12-03 13:56:00 +00:00
|
|
|
ackSeg.ReceivingNext = w.nextNumber
|
|
|
|
ackSeg.ReceivingWindow = w.nextNumber + w.windowSize
|
2018-07-08 21:03:00 +00:00
|
|
|
ackSeg.Option = 0
|
2017-12-03 13:56:00 +00:00
|
|
|
if w.conn.State() == StateReadyToClose {
|
2016-07-14 20:52:00 +00:00
|
|
|
ackSeg.Option = SegmentOptionClose
|
2016-07-02 19:26:50 +00:00
|
|
|
}
|
2017-12-03 13:56:00 +00:00
|
|
|
return w.conn.output.Write(ackSeg)
|
2016-07-02 19:26:50 +00:00
|
|
|
}
|
|
|
|
|
2017-12-03 13:56:00 +00:00
|
|
|
func (*ReceivingWorker) CloseRead() {
|
2016-07-02 19:26:50 +00:00
|
|
|
}
|
2016-10-10 14:50:54 +00:00
|
|
|
|
2017-12-03 13:56:00 +00:00
|
|
|
func (w *ReceivingWorker) UpdateNecessary() bool {
|
|
|
|
w.RLock()
|
|
|
|
defer w.RUnlock()
|
2017-02-17 23:04:25 +00:00
|
|
|
|
2017-12-03 13:56:00 +00:00
|
|
|
return len(w.acklist.numbers) > 0
|
2016-10-10 14:50:54 +00:00
|
|
|
}
|