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

     1  // +build !confonly
     2  
     3  package kcp
     4  
     5  import (
     6  	"container/list"
     7  	"sync"
     8  
     9  	"v2ray.com/core/common/buf"
    10  )
    11  
    12  type SendingWindow struct {
    13  	cache             *list.List
    14  	totalInFlightSize uint32
    15  	writer            SegmentWriter
    16  	onPacketLoss      func(uint32)
    17  }
    18  
    19  func NewSendingWindow(writer SegmentWriter, onPacketLoss func(uint32)) *SendingWindow {
    20  	window := &SendingWindow{
    21  		cache:        list.New(),
    22  		writer:       writer,
    23  		onPacketLoss: onPacketLoss,
    24  	}
    25  	return window
    26  }
    27  
    28  func (sw *SendingWindow) Release() {
    29  	if sw == nil {
    30  		return
    31  	}
    32  	for sw.cache.Len() > 0 {
    33  		seg := sw.cache.Front().Value.(*DataSegment)
    34  		seg.Release()
    35  		sw.cache.Remove(sw.cache.Front())
    36  	}
    37  }
    38  
    39  func (sw *SendingWindow) Len() uint32 {
    40  	return uint32(sw.cache.Len())
    41  }
    42  
    43  func (sw *SendingWindow) IsEmpty() bool {
    44  	return sw.cache.Len() == 0
    45  }
    46  
    47  func (sw *SendingWindow) Push(number uint32, b *buf.Buffer) {
    48  	seg := NewDataSegment()
    49  	seg.Number = number
    50  	seg.payload = b
    51  
    52  	sw.cache.PushBack(seg)
    53  }
    54  
    55  func (sw *SendingWindow) FirstNumber() uint32 {
    56  	return sw.cache.Front().Value.(*DataSegment).Number
    57  }
    58  
    59  func (sw *SendingWindow) Clear(una uint32) {
    60  	for !sw.IsEmpty() {
    61  		seg := sw.cache.Front().Value.(*DataSegment)
    62  		if seg.Number >= una {
    63  			break
    64  		}
    65  		seg.Release()
    66  		sw.cache.Remove(sw.cache.Front())
    67  	}
    68  }
    69  
    70  func (sw *SendingWindow) HandleFastAck(number uint32, rto uint32) {
    71  	if sw.IsEmpty() {
    72  		return
    73  	}
    74  
    75  	sw.Visit(func(seg *DataSegment) bool {
    76  		if number == seg.Number || number-seg.Number > 0x7FFFFFFF {
    77  			return false
    78  		}
    79  
    80  		if seg.transmit > 0 && seg.timeout > rto/3 {
    81  			seg.timeout -= rto / 3
    82  		}
    83  		return true
    84  	})
    85  }
    86  
    87  func (sw *SendingWindow) Visit(visitor func(seg *DataSegment) bool) {
    88  	if sw.IsEmpty() {
    89  		return
    90  	}
    91  
    92  	for e := sw.cache.Front(); e != nil; e = e.Next() {
    93  		seg := e.Value.(*DataSegment)
    94  		if !visitor(seg) {
    95  			break
    96  		}
    97  	}
    98  }
    99  
   100  func (sw *SendingWindow) Flush(current uint32, rto uint32, maxInFlightSize uint32) {
   101  	if sw.IsEmpty() {
   102  		return
   103  	}
   104  
   105  	var lost uint32
   106  	var inFlightSize uint32
   107  
   108  	sw.Visit(func(segment *DataSegment) bool {
   109  		if current-segment.timeout >= 0x7FFFFFFF {
   110  			return true
   111  		}
   112  		if segment.transmit == 0 {
   113  			// First time
   114  			sw.totalInFlightSize++
   115  		} else {
   116  			lost++
   117  		}
   118  		segment.timeout = current + rto
   119  
   120  		segment.Timestamp = current
   121  		segment.transmit++
   122  		sw.writer.Write(segment)
   123  		inFlightSize++
   124  		return inFlightSize < maxInFlightSize
   125  	})
   126  
   127  	if sw.onPacketLoss != nil && inFlightSize > 0 && sw.totalInFlightSize != 0 {
   128  		rate := lost * 100 / sw.totalInFlightSize
   129  		sw.onPacketLoss(rate)
   130  	}
   131  }
   132  
   133  func (sw *SendingWindow) Remove(number uint32) bool {
   134  	if sw.IsEmpty() {
   135  		return false
   136  	}
   137  
   138  	for e := sw.cache.Front(); e != nil; e = e.Next() {
   139  		seg := e.Value.(*DataSegment)
   140  		if seg.Number > number {
   141  			return false
   142  		} else if seg.Number == number {
   143  			if sw.totalInFlightSize > 0 {
   144  				sw.totalInFlightSize--
   145  			}
   146  			seg.Release()
   147  			sw.cache.Remove(e)
   148  			return true
   149  		}
   150  	}
   151  
   152  	return false
   153  }
   154  
   155  type SendingWorker struct {
   156  	sync.RWMutex
   157  	conn                       *Connection
   158  	window                     *SendingWindow
   159  	firstUnacknowledged        uint32
   160  	nextNumber                 uint32
   161  	remoteNextNumber           uint32
   162  	controlWindow              uint32
   163  	fastResend                 uint32
   164  	windowSize                 uint32
   165  	firstUnacknowledgedUpdated bool
   166  	closed                     bool
   167  }
   168  
   169  func NewSendingWorker(kcp *Connection) *SendingWorker {
   170  	worker := &SendingWorker{
   171  		conn:             kcp,
   172  		fastResend:       2,
   173  		remoteNextNumber: 32,
   174  		controlWindow:    kcp.Config.GetSendingInFlightSize(),
   175  		windowSize:       kcp.Config.GetSendingBufferSize(),
   176  	}
   177  	worker.window = NewSendingWindow(worker, worker.OnPacketLoss)
   178  	return worker
   179  }
   180  
   181  func (w *SendingWorker) Release() {
   182  	w.Lock()
   183  	w.window.Release()
   184  	w.closed = true
   185  	w.Unlock()
   186  }
   187  
   188  func (w *SendingWorker) ProcessReceivingNext(nextNumber uint32) {
   189  	w.Lock()
   190  	defer w.Unlock()
   191  
   192  	w.ProcessReceivingNextWithoutLock(nextNumber)
   193  }
   194  
   195  func (w *SendingWorker) ProcessReceivingNextWithoutLock(nextNumber uint32) {
   196  	w.window.Clear(nextNumber)
   197  	w.FindFirstUnacknowledged()
   198  }
   199  
   200  func (w *SendingWorker) FindFirstUnacknowledged() {
   201  	first := w.firstUnacknowledged
   202  	if !w.window.IsEmpty() {
   203  		w.firstUnacknowledged = w.window.FirstNumber()
   204  	} else {
   205  		w.firstUnacknowledged = w.nextNumber
   206  	}
   207  	if first != w.firstUnacknowledged {
   208  		w.firstUnacknowledgedUpdated = true
   209  	}
   210  }
   211  
   212  func (w *SendingWorker) processAck(number uint32) bool {
   213  	// number < v.firstUnacknowledged || number >= v.nextNumber
   214  	if number-w.firstUnacknowledged > 0x7FFFFFFF || number-w.nextNumber < 0x7FFFFFFF {
   215  		return false
   216  	}
   217  
   218  	removed := w.window.Remove(number)
   219  	if removed {
   220  		w.FindFirstUnacknowledged()
   221  	}
   222  	return removed
   223  }
   224  
   225  func (w *SendingWorker) ProcessSegment(current uint32, seg *AckSegment, rto uint32) {
   226  	defer seg.Release()
   227  
   228  	w.Lock()
   229  	defer w.Unlock()
   230  
   231  	if w.closed {
   232  		return
   233  	}
   234  
   235  	if w.remoteNextNumber < seg.ReceivingWindow {
   236  		w.remoteNextNumber = seg.ReceivingWindow
   237  	}
   238  	w.ProcessReceivingNextWithoutLock(seg.ReceivingNext)
   239  
   240  	if seg.IsEmpty() {
   241  		return
   242  	}
   243  
   244  	var maxack uint32
   245  	var maxackRemoved bool
   246  	for _, number := range seg.NumberList {
   247  		removed := w.processAck(number)
   248  		if maxack < number {
   249  			maxack = number
   250  			maxackRemoved = removed
   251  		}
   252  	}
   253  
   254  	if maxackRemoved {
   255  		w.window.HandleFastAck(maxack, rto)
   256  		if current-seg.Timestamp < 10000 {
   257  			w.conn.roundTrip.Update(current-seg.Timestamp, current)
   258  		}
   259  	}
   260  }
   261  
   262  func (w *SendingWorker) Push(b *buf.Buffer) bool {
   263  	w.Lock()
   264  	defer w.Unlock()
   265  
   266  	if w.closed {
   267  		return false
   268  	}
   269  
   270  	if w.window.Len() > w.windowSize {
   271  		return false
   272  	}
   273  
   274  	w.window.Push(w.nextNumber, b)
   275  	w.nextNumber++
   276  	return true
   277  }
   278  
   279  func (w *SendingWorker) Write(seg Segment) error {
   280  	dataSeg := seg.(*DataSegment)
   281  
   282  	dataSeg.Conv = w.conn.meta.Conversation
   283  	dataSeg.SendingNext = w.firstUnacknowledged
   284  	dataSeg.Option = 0
   285  	if w.conn.State() == StateReadyToClose {
   286  		dataSeg.Option = SegmentOptionClose
   287  	}
   288  
   289  	return w.conn.output.Write(dataSeg)
   290  }
   291  
   292  func (w *SendingWorker) OnPacketLoss(lossRate uint32) {
   293  	if !w.conn.Config.Congestion || w.conn.roundTrip.Timeout() == 0 {
   294  		return
   295  	}
   296  
   297  	if lossRate >= 15 {
   298  		w.controlWindow = 3 * w.controlWindow / 4
   299  	} else if lossRate <= 5 {
   300  		w.controlWindow += w.controlWindow / 4
   301  	}
   302  	if w.controlWindow < 16 {
   303  		w.controlWindow = 16
   304  	}
   305  	if w.controlWindow > 2*w.conn.Config.GetSendingInFlightSize() {
   306  		w.controlWindow = 2 * w.conn.Config.GetSendingInFlightSize()
   307  	}
   308  }
   309  
   310  func (w *SendingWorker) Flush(current uint32) {
   311  	w.Lock()
   312  
   313  	if w.closed {
   314  		w.Unlock()
   315  		return
   316  	}
   317  
   318  	cwnd := w.firstUnacknowledged + w.conn.Config.GetSendingInFlightSize()
   319  	if cwnd > w.remoteNextNumber {
   320  		cwnd = w.remoteNextNumber
   321  	}
   322  	if w.conn.Config.Congestion && cwnd > w.firstUnacknowledged+w.controlWindow {
   323  		cwnd = w.firstUnacknowledged + w.controlWindow
   324  	}
   325  
   326  	if !w.window.IsEmpty() {
   327  		w.window.Flush(current, w.conn.roundTrip.Timeout(), cwnd)
   328  		w.firstUnacknowledgedUpdated = false
   329  	}
   330  
   331  	updated := w.firstUnacknowledgedUpdated
   332  	w.firstUnacknowledgedUpdated = false
   333  
   334  	w.Unlock()
   335  
   336  	if updated {
   337  		w.conn.Ping(current, CommandPing)
   338  	}
   339  }
   340  
   341  func (w *SendingWorker) CloseWrite() {
   342  	w.Lock()
   343  	defer w.Unlock()
   344  
   345  	w.window.Clear(0xFFFFFFFF)
   346  }
   347  
   348  func (w *SendingWorker) IsEmpty() bool {
   349  	w.RLock()
   350  	defer w.RUnlock()
   351  
   352  	return w.window.IsEmpty()
   353  }
   354  
   355  func (w *SendingWorker) UpdateNecessary() bool {
   356  	return !w.IsEmpty()
   357  }
   358  
   359  func (w *SendingWorker) FirstUnacknowledged() uint32 {
   360  	w.RLock()
   361  	defer w.RUnlock()
   362  
   363  	return w.firstUnacknowledged
   364  }