|  | @@ -6,7 +6,6 @@
 | 
	
		
			
				|  |  |  package kcp
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import (
 | 
	
		
			
				|  |  | -	"github.com/v2ray/v2ray-core/common/alloc"
 | 
	
		
			
				|  |  |  	"github.com/v2ray/v2ray-core/common/log"
 | 
	
		
			
				|  |  |  )
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -35,14 +34,11 @@ type KCP struct {
 | 
	
		
			
				|  |  |  	lastPingTime     uint32
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	mss                        uint32
 | 
	
		
			
				|  |  | -	snd_una, snd_nxt           uint32
 | 
	
		
			
				|  |  |  	rx_rttvar, rx_srtt, rx_rto uint32
 | 
	
		
			
				|  |  | -	snd_wnd, rmt_wnd, cwnd     uint32
 | 
	
		
			
				|  |  |  	current, interval          uint32
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	snd_queue       *SendingQueue
 | 
	
		
			
				|  |  | -	snd_buf         *SendingWindow
 | 
	
		
			
				|  |  |  	receivingWorker *ReceivingWorker
 | 
	
		
			
				|  |  | +	sendingWorker   *SendingWorker
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	fastresend        uint32
 | 
	
		
			
				|  |  |  	congestionControl bool
 | 
	
	
		
			
				|  | @@ -55,18 +51,14 @@ func NewKCP(conv uint16, output *AuthenticationWriter) *KCP {
 | 
	
		
			
				|  |  |  	log.Debug("KCP|Core: creating KCP ", conv)
 | 
	
		
			
				|  |  |  	kcp := new(KCP)
 | 
	
		
			
				|  |  |  	kcp.conv = conv
 | 
	
		
			
				|  |  | -	kcp.snd_wnd = effectiveConfig.GetSendingWindowSize()
 | 
	
		
			
				|  |  | -	kcp.rmt_wnd = 32
 | 
	
		
			
				|  |  |  	kcp.mss = output.Mtu() - DataSegmentOverhead
 | 
	
		
			
				|  |  |  	kcp.rx_rto = 100
 | 
	
		
			
				|  |  |  	kcp.interval = effectiveConfig.Tti
 | 
	
		
			
				|  |  |  	kcp.output = NewSegmentWriter(output)
 | 
	
		
			
				|  |  | -	kcp.snd_queue = NewSendingQueue(effectiveConfig.GetSendingQueueSize())
 | 
	
		
			
				|  |  | -	kcp.snd_buf = NewSendingWindow(kcp, effectiveConfig.GetSendingWindowSize())
 | 
	
		
			
				|  |  | -	kcp.cwnd = kcp.snd_wnd
 | 
	
		
			
				|  |  |  	kcp.receivingWorker = NewReceivingWorker(kcp)
 | 
	
		
			
				|  |  |  	kcp.fastresend = 2
 | 
	
		
			
				|  |  |  	kcp.congestionControl = effectiveConfig.Congestion
 | 
	
		
			
				|  |  | +	kcp.sendingWorker = NewSendingWorker(kcp)
 | 
	
		
			
				|  |  |  	return kcp
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -78,11 +70,13 @@ func (kcp *KCP) SetState(state State) {
 | 
	
		
			
				|  |  |  	case StateReadyToClose:
 | 
	
		
			
				|  |  |  		kcp.receivingWorker.CloseRead()
 | 
	
		
			
				|  |  |  	case StatePeerClosed:
 | 
	
		
			
				|  |  | -		kcp.ClearSendQueue()
 | 
	
		
			
				|  |  | +		kcp.sendingWorker.CloseWrite()
 | 
	
		
			
				|  |  |  	case StateTerminating:
 | 
	
		
			
				|  |  |  		kcp.receivingWorker.CloseRead()
 | 
	
		
			
				|  |  | +		kcp.sendingWorker.CloseWrite()
 | 
	
		
			
				|  |  |  	case StateTerminated:
 | 
	
		
			
				|  |  |  		kcp.receivingWorker.CloseRead()
 | 
	
		
			
				|  |  | +		kcp.sendingWorker.CloseWrite()
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -110,26 +104,6 @@ func (kcp *KCP) OnClose() {
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -// Send is user/upper level send, returns below zero for error
 | 
	
		
			
				|  |  | -func (kcp *KCP) Send(buffer []byte) int {
 | 
	
		
			
				|  |  | -	nBytes := 0
 | 
	
		
			
				|  |  | -	for len(buffer) > 0 && !kcp.snd_queue.IsFull() {
 | 
	
		
			
				|  |  | -		var size int
 | 
	
		
			
				|  |  | -		if len(buffer) > int(kcp.mss) {
 | 
	
		
			
				|  |  | -			size = int(kcp.mss)
 | 
	
		
			
				|  |  | -		} else {
 | 
	
		
			
				|  |  | -			size = len(buffer)
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -		seg := &DataSegment{
 | 
	
		
			
				|  |  | -			Data: alloc.NewSmallBuffer().Clear().Append(buffer[:size]),
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -		kcp.snd_queue.Push(seg)
 | 
	
		
			
				|  |  | -		buffer = buffer[size:]
 | 
	
		
			
				|  |  | -		nBytes += size
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	return nBytes
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  // https://tools.ietf.org/html/rfc6298
 | 
	
		
			
				|  |  |  func (kcp *KCP) update_ack(rtt int32) {
 | 
	
		
			
				|  |  |  	if kcp.rx_srtt == 0 {
 | 
	
	
		
			
				|  | @@ -159,46 +133,11 @@ func (kcp *KCP) update_ack(rtt int32) {
 | 
	
		
			
				|  |  |  	kcp.rx_rto = rto * 3 / 2
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -func (kcp *KCP) shrink_buf() {
 | 
	
		
			
				|  |  | -	prevUna := kcp.snd_una
 | 
	
		
			
				|  |  | -	if kcp.snd_buf.Len() > 0 {
 | 
	
		
			
				|  |  | -		seg := kcp.snd_buf.First()
 | 
	
		
			
				|  |  | -		kcp.snd_una = seg.Number
 | 
	
		
			
				|  |  | -	} else {
 | 
	
		
			
				|  |  | -		kcp.snd_una = kcp.snd_nxt
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	if kcp.snd_una != prevUna {
 | 
	
		
			
				|  |  | -		kcp.sendingUpdated = true
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (kcp *KCP) parse_ack(sn uint32) {
 | 
	
		
			
				|  |  | -	if _itimediff(sn, kcp.snd_una) < 0 || _itimediff(sn, kcp.snd_nxt) >= 0 {
 | 
	
		
			
				|  |  | -		return
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	kcp.snd_buf.Remove(sn - kcp.snd_una)
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (kcp *KCP) parse_fastack(sn uint32) {
 | 
	
		
			
				|  |  | -	if _itimediff(sn, kcp.snd_una) < 0 || _itimediff(sn, kcp.snd_nxt) >= 0 {
 | 
	
		
			
				|  |  | -		return
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	kcp.snd_buf.HandleFastAck(sn)
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (kcp *KCP) HandleReceivingNext(receivingNext uint32) {
 | 
	
		
			
				|  |  | -	kcp.snd_buf.Clear(receivingNext)
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  // Input when you received a low level packet (eg. UDP packet), call it
 | 
	
		
			
				|  |  |  func (kcp *KCP) Input(data []byte) int {
 | 
	
		
			
				|  |  |  	kcp.lastIncomingTime = kcp.current
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	var seg ISegment
 | 
	
		
			
				|  |  | -	var maxack uint32
 | 
	
		
			
				|  |  | -	var flag int
 | 
	
		
			
				|  |  |  	for {
 | 
	
		
			
				|  |  |  		seg, data = ReadSegment(data)
 | 
	
		
			
				|  |  |  		if seg == nil {
 | 
	
	
		
			
				|  | @@ -212,26 +151,7 @@ func (kcp *KCP) Input(data []byte) int {
 | 
	
		
			
				|  |  |  			kcp.lastPayloadTime = kcp.current
 | 
	
		
			
				|  |  |  		case *AckSegment:
 | 
	
		
			
				|  |  |  			kcp.HandleOption(seg.Opt)
 | 
	
		
			
				|  |  | -			if kcp.rmt_wnd < seg.ReceivingWindow {
 | 
	
		
			
				|  |  | -				kcp.rmt_wnd = seg.ReceivingWindow
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -			kcp.HandleReceivingNext(seg.ReceivingNext)
 | 
	
		
			
				|  |  | -			kcp.shrink_buf()
 | 
	
		
			
				|  |  | -			for i := 0; i < int(seg.Count); i++ {
 | 
	
		
			
				|  |  | -				ts := seg.TimestampList[i]
 | 
	
		
			
				|  |  | -				sn := seg.NumberList[i]
 | 
	
		
			
				|  |  | -				if _itimediff(kcp.current, ts) >= 0 {
 | 
	
		
			
				|  |  | -					kcp.update_ack(_itimediff(kcp.current, ts))
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | -				kcp.parse_ack(sn)
 | 
	
		
			
				|  |  | -				kcp.shrink_buf()
 | 
	
		
			
				|  |  | -				if flag == 0 {
 | 
	
		
			
				|  |  | -					flag = 1
 | 
	
		
			
				|  |  | -					maxack = sn
 | 
	
		
			
				|  |  | -				} else if _itimediff(sn, maxack) > 0 {
 | 
	
		
			
				|  |  | -					maxack = sn
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | +			kcp.sendingWorker.ProcessAckSegment(seg)
 | 
	
		
			
				|  |  |  			kcp.lastPayloadTime = kcp.current
 | 
	
		
			
				|  |  |  		case *CmdOnlySegment:
 | 
	
		
			
				|  |  |  			kcp.HandleOption(seg.Opt)
 | 
	
	
		
			
				|  | @@ -244,17 +164,12 @@ func (kcp *KCP) Input(data []byte) int {
 | 
	
		
			
				|  |  |  					kcp.SetState(StateTerminated)
 | 
	
		
			
				|  |  |  				}
 | 
	
		
			
				|  |  |  			}
 | 
	
		
			
				|  |  | -			kcp.HandleReceivingNext(seg.ReceivinNext)
 | 
	
		
			
				|  |  | +			kcp.sendingWorker.ProcessReceivingNext(seg.ReceivinNext)
 | 
	
		
			
				|  |  |  			kcp.receivingWorker.ProcessSendingNext(seg.SendingNext)
 | 
	
		
			
				|  |  | -			kcp.shrink_buf()
 | 
	
		
			
				|  |  |  		default:
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	if flag != 0 {
 | 
	
		
			
				|  |  | -		kcp.parse_fastack(maxack)
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  	return 0
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -284,42 +199,16 @@ func (kcp *KCP) flush() {
 | 
	
		
			
				|  |  |  		kcp.SetState(StateTerminating)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	current := kcp.current
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  	// flush acknowledges
 | 
	
		
			
				|  |  |  	kcp.receivingWorker.Flush()
 | 
	
		
			
				|  |  | +	kcp.sendingWorker.Flush()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	// calculate window size
 | 
	
		
			
				|  |  | -	cwnd := kcp.snd_una + kcp.snd_wnd
 | 
	
		
			
				|  |  | -	if cwnd > kcp.rmt_wnd {
 | 
	
		
			
				|  |  | -		cwnd = kcp.rmt_wnd
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	if kcp.congestionControl && cwnd > kcp.snd_una+kcp.cwnd {
 | 
	
		
			
				|  |  | -		cwnd = kcp.snd_una + kcp.cwnd
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	for !kcp.snd_queue.IsEmpty() && _itimediff(kcp.snd_nxt, cwnd) < 0 {
 | 
	
		
			
				|  |  | -		seg := kcp.snd_queue.Pop()
 | 
	
		
			
				|  |  | -		seg.Conv = kcp.conv
 | 
	
		
			
				|  |  | -		seg.Number = kcp.snd_nxt
 | 
	
		
			
				|  |  | -		seg.timeout = current
 | 
	
		
			
				|  |  | -		seg.ackSkipped = 0
 | 
	
		
			
				|  |  | -		seg.transmit = 0
 | 
	
		
			
				|  |  | -		kcp.snd_buf.Push(seg)
 | 
	
		
			
				|  |  | -		kcp.snd_nxt++
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	// flush data segments
 | 
	
		
			
				|  |  | -	if kcp.snd_buf.Flush() {
 | 
	
		
			
				|  |  | -		kcp.sendingUpdated = false
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	if kcp.sendingUpdated || kcp.receivingWorker.PingNecessary() || _itimediff(kcp.current, kcp.lastPingTime) >= 5000 {
 | 
	
		
			
				|  |  | +	if kcp.sendingWorker.PingNecessary() || kcp.receivingWorker.PingNecessary() || _itimediff(kcp.current, kcp.lastPingTime) >= 5000 {
 | 
	
		
			
				|  |  |  		seg := &CmdOnlySegment{
 | 
	
		
			
				|  |  |  			Conv:         kcp.conv,
 | 
	
		
			
				|  |  |  			Cmd:          SegmentCommandPing,
 | 
	
		
			
				|  |  |  			ReceivinNext: kcp.receivingWorker.nextNumber,
 | 
	
		
			
				|  |  | -			SendingNext:  kcp.snd_una,
 | 
	
		
			
				|  |  | +			SendingNext:  kcp.sendingWorker.firstUnacknowledged,
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  		if kcp.state == StateReadyToClose {
 | 
	
		
			
				|  |  |  			seg.Opt = SegmentOptionClose
 | 
	
	
		
			
				|  | @@ -334,23 +223,6 @@ func (kcp *KCP) flush() {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -func (kcp *KCP) HandleLost(lost bool) {
 | 
	
		
			
				|  |  | -	if !kcp.congestionControl {
 | 
	
		
			
				|  |  | -		return
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	if lost {
 | 
	
		
			
				|  |  | -		kcp.cwnd = 3 * kcp.cwnd / 4
 | 
	
		
			
				|  |  | -	} else {
 | 
	
		
			
				|  |  | -		kcp.cwnd += kcp.cwnd / 4
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	if kcp.cwnd < 4 {
 | 
	
		
			
				|  |  | -		kcp.cwnd = 4
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	if kcp.cwnd > kcp.snd_wnd {
 | 
	
		
			
				|  |  | -		kcp.cwnd = kcp.snd_wnd
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  // Update updates state (call it repeatedly, every 10ms-100ms), or you can ask
 | 
	
		
			
				|  |  |  // ikcp_check when to call it again (without ikcp_input/_send calling).
 | 
	
		
			
				|  |  |  // 'current' - current timestamp in millisec.
 | 
	
	
		
			
				|  | @@ -358,13 +230,3 @@ func (kcp *KCP) Update(current uint32) {
 | 
	
		
			
				|  |  |  	kcp.current = current
 | 
	
		
			
				|  |  |  	kcp.flush()
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// WaitSnd gets how many packet is waiting to be sent
 | 
	
		
			
				|  |  | -func (kcp *KCP) WaitSnd() uint32 {
 | 
	
		
			
				|  |  | -	return uint32(kcp.snd_buf.Len()) + kcp.snd_queue.Len()
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (this *KCP) ClearSendQueue() {
 | 
	
		
			
				|  |  | -	this.snd_queue.Clear()
 | 
	
		
			
				|  |  | -	this.snd_buf.Clear(0xFFFFFFFF)
 | 
	
		
			
				|  |  | -}
 |