github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/transport/internet/kcp/receiving.go (about)

     1  // +build !confonly
     2  
     3  package kcp
     4  
     5  import (
     6  	"sync"
     7  
     8  	"v2ray.com/core/common/buf"
     9  )
    10  
    11  type ReceivingWindow struct {
    12  	cache map[uint32]*DataSegment
    13  }
    14  
    15  func NewReceivingWindow() *ReceivingWindow {
    16  	return &ReceivingWindow{
    17  		cache: make(map[uint32]*DataSegment),
    18  	}
    19  }
    20  
    21  func (w *ReceivingWindow) Set(id uint32, value *DataSegment) bool {
    22  	_, f := w.cache[id]
    23  	if f {
    24  		return false
    25  	}
    26  	w.cache[id] = value
    27  	return true
    28  }
    29  
    30  func (w *ReceivingWindow) Has(id uint32) bool {
    31  	_, f := w.cache[id]
    32  	return f
    33  }
    34  
    35  func (w *ReceivingWindow) Remove(id uint32) *DataSegment {
    36  	v, f := w.cache[id]
    37  	if !f {
    38  		return nil
    39  	}
    40  	delete(w.cache, id)
    41  	return v
    42  }
    43  
    44  type AckList struct {
    45  	writer     SegmentWriter
    46  	timestamps []uint32
    47  	numbers    []uint32
    48  	nextFlush  []uint32
    49  
    50  	flushCandidates []uint32
    51  	dirty           bool
    52  }
    53  
    54  func NewAckList(writer SegmentWriter) *AckList {
    55  	return &AckList{
    56  		writer:          writer,
    57  		timestamps:      make([]uint32, 0, 128),
    58  		numbers:         make([]uint32, 0, 128),
    59  		nextFlush:       make([]uint32, 0, 128),
    60  		flushCandidates: make([]uint32, 0, 128),
    61  	}
    62  }
    63  
    64  func (l *AckList) Add(number uint32, timestamp uint32) {
    65  	l.timestamps = append(l.timestamps, timestamp)
    66  	l.numbers = append(l.numbers, number)
    67  	l.nextFlush = append(l.nextFlush, 0)
    68  	l.dirty = true
    69  }
    70  
    71  func (l *AckList) Clear(una uint32) {
    72  	count := 0
    73  	for i := 0; i < len(l.numbers); i++ {
    74  		if l.numbers[i] < una {
    75  			continue
    76  		}
    77  		if i != count {
    78  			l.numbers[count] = l.numbers[i]
    79  			l.timestamps[count] = l.timestamps[i]
    80  			l.nextFlush[count] = l.nextFlush[i]
    81  		}
    82  		count++
    83  	}
    84  	if count < len(l.numbers) {
    85  		l.numbers = l.numbers[:count]
    86  		l.timestamps = l.timestamps[:count]
    87  		l.nextFlush = l.nextFlush[:count]
    88  		l.dirty = true
    89  	}
    90  }
    91  
    92  func (l *AckList) Flush(current uint32, rto uint32) {
    93  	l.flushCandidates = l.flushCandidates[:0]
    94  
    95  	seg := NewAckSegment()
    96  	for i := 0; i < len(l.numbers); i++ {
    97  		if l.nextFlush[i] > current {
    98  			if len(l.flushCandidates) < cap(l.flushCandidates) {
    99  				l.flushCandidates = append(l.flushCandidates, l.numbers[i])
   100  			}
   101  			continue
   102  		}
   103  		seg.PutNumber(l.numbers[i])
   104  		seg.PutTimestamp(l.timestamps[i])
   105  		timeout := rto / 2
   106  		if timeout < 20 {
   107  			timeout = 20
   108  		}
   109  		l.nextFlush[i] = current + timeout
   110  
   111  		if seg.IsFull() {
   112  			l.writer.Write(seg)
   113  			seg.Release()
   114  			seg = NewAckSegment()
   115  			l.dirty = false
   116  		}
   117  	}
   118  
   119  	if l.dirty || !seg.IsEmpty() {
   120  		for _, number := range l.flushCandidates {
   121  			if seg.IsFull() {
   122  				break
   123  			}
   124  			seg.PutNumber(number)
   125  		}
   126  		l.writer.Write(seg)
   127  		l.dirty = false
   128  	}
   129  
   130  	seg.Release()
   131  }
   132  
   133  type ReceivingWorker struct {
   134  	sync.RWMutex
   135  	conn       *Connection
   136  	leftOver   buf.MultiBuffer
   137  	window     *ReceivingWindow
   138  	acklist    *AckList
   139  	nextNumber uint32
   140  	windowSize uint32
   141  }
   142  
   143  func NewReceivingWorker(kcp *Connection) *ReceivingWorker {
   144  	worker := &ReceivingWorker{
   145  		conn:       kcp,
   146  		window:     NewReceivingWindow(),
   147  		windowSize: kcp.Config.GetReceivingInFlightSize(),
   148  	}
   149  	worker.acklist = NewAckList(worker)
   150  	return worker
   151  }
   152  
   153  func (w *ReceivingWorker) Release() {
   154  	w.Lock()
   155  	buf.ReleaseMulti(w.leftOver)
   156  	w.leftOver = nil
   157  	w.Unlock()
   158  }
   159  
   160  func (w *ReceivingWorker) ProcessSendingNext(number uint32) {
   161  	w.Lock()
   162  	defer w.Unlock()
   163  
   164  	w.acklist.Clear(number)
   165  }
   166  
   167  func (w *ReceivingWorker) ProcessSegment(seg *DataSegment) {
   168  	w.Lock()
   169  	defer w.Unlock()
   170  
   171  	number := seg.Number
   172  	idx := number - w.nextNumber
   173  	if idx >= w.windowSize {
   174  		return
   175  	}
   176  	w.acklist.Clear(seg.SendingNext)
   177  	w.acklist.Add(number, seg.Timestamp)
   178  
   179  	if !w.window.Set(seg.Number, seg) {
   180  		seg.Release()
   181  	}
   182  }
   183  
   184  func (w *ReceivingWorker) ReadMultiBuffer() buf.MultiBuffer {
   185  	if w.leftOver != nil {
   186  		mb := w.leftOver
   187  		w.leftOver = nil
   188  		return mb
   189  	}
   190  
   191  	mb := make(buf.MultiBuffer, 0, 32)
   192  
   193  	w.Lock()
   194  	defer w.Unlock()
   195  	for {
   196  		seg := w.window.Remove(w.nextNumber)
   197  		if seg == nil {
   198  			break
   199  		}
   200  		w.nextNumber++
   201  		mb = append(mb, seg.Detach())
   202  		seg.Release()
   203  	}
   204  
   205  	return mb
   206  }
   207  
   208  func (w *ReceivingWorker) Read(b []byte) int {
   209  	mb := w.ReadMultiBuffer()
   210  	if mb.IsEmpty() {
   211  		return 0
   212  	}
   213  	mb, nBytes := buf.SplitBytes(mb, b)
   214  	if !mb.IsEmpty() {
   215  		w.leftOver = mb
   216  	}
   217  	return nBytes
   218  }
   219  
   220  func (w *ReceivingWorker) IsDataAvailable() bool {
   221  	w.RLock()
   222  	defer w.RUnlock()
   223  	return w.window.Has(w.nextNumber)
   224  }
   225  
   226  func (w *ReceivingWorker) NextNumber() uint32 {
   227  	w.RLock()
   228  	defer w.RUnlock()
   229  
   230  	return w.nextNumber
   231  }
   232  
   233  func (w *ReceivingWorker) Flush(current uint32) {
   234  	w.Lock()
   235  	defer w.Unlock()
   236  
   237  	w.acklist.Flush(current, w.conn.roundTrip.Timeout())
   238  }
   239  
   240  func (w *ReceivingWorker) Write(seg Segment) error {
   241  	ackSeg := seg.(*AckSegment)
   242  	ackSeg.Conv = w.conn.meta.Conversation
   243  	ackSeg.ReceivingNext = w.nextNumber
   244  	ackSeg.ReceivingWindow = w.nextNumber + w.windowSize
   245  	ackSeg.Option = 0
   246  	if w.conn.State() == StateReadyToClose {
   247  		ackSeg.Option = SegmentOptionClose
   248  	}
   249  	return w.conn.output.Write(ackSeg)
   250  }
   251  
   252  func (*ReceivingWorker) CloseRead() {
   253  }
   254  
   255  func (w *ReceivingWorker) UpdateNecessary() bool {
   256  	w.RLock()
   257  	defer w.RUnlock()
   258  
   259  	return len(w.acklist.numbers) > 0
   260  }