|  | @@ -54,7 +54,7 @@ type KCP struct {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	snd_queue *SendingQueue
 | 
	
		
			
				|  |  |  	rcv_queue *ReceivingQueue
 | 
	
		
			
				|  |  | -	snd_buf   []*DataSegment
 | 
	
		
			
				|  |  | +	snd_buf   *SendingWindow
 | 
	
		
			
				|  |  |  	rcv_buf   *ReceivingWindow
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	acklist *ACKList
 | 
	
	
		
			
				|  | @@ -82,6 +82,7 @@ func NewKCP(conv uint16, mtu uint32, sendingWindowSize uint32, receivingWindowSi
 | 
	
		
			
				|  |  |  	kcp.snd_queue = NewSendingQueue(sendingQueueSize)
 | 
	
		
			
				|  |  |  	kcp.rcv_queue = NewReceivingQueue()
 | 
	
		
			
				|  |  |  	kcp.acklist = NewACKList(kcp)
 | 
	
		
			
				|  |  | +	kcp.snd_buf = NewSendingWindow(kcp, sendingWindowSize)
 | 
	
		
			
				|  |  |  	kcp.cwnd = kcp.snd_wnd
 | 
	
		
			
				|  |  |  	return kcp
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -194,8 +195,8 @@ func (kcp *KCP) update_ack(rtt int32) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  func (kcp *KCP) shrink_buf() {
 | 
	
		
			
				|  |  |  	prevUna := kcp.snd_una
 | 
	
		
			
				|  |  | -	if len(kcp.snd_buf) > 0 {
 | 
	
		
			
				|  |  | -		seg := kcp.snd_buf[0]
 | 
	
		
			
				|  |  | +	if kcp.snd_buf.Len() > 0 {
 | 
	
		
			
				|  |  | +		seg := kcp.snd_buf.First()
 | 
	
		
			
				|  |  |  		kcp.snd_una = seg.Number
 | 
	
		
			
				|  |  |  	} else {
 | 
	
		
			
				|  |  |  		kcp.snd_una = kcp.snd_nxt
 | 
	
	
		
			
				|  | @@ -210,16 +211,7 @@ func (kcp *KCP) parse_ack(sn uint32) {
 | 
	
		
			
				|  |  |  		return
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	for k, seg := range kcp.snd_buf {
 | 
	
		
			
				|  |  | -		if sn == seg.Number {
 | 
	
		
			
				|  |  | -			kcp.snd_buf = append(kcp.snd_buf[:k], kcp.snd_buf[k+1:]...)
 | 
	
		
			
				|  |  | -			seg.Release()
 | 
	
		
			
				|  |  | -			break
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -		if _itimediff(sn, seg.Number) < 0 {
 | 
	
		
			
				|  |  | -			break
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | +	kcp.snd_buf.Remove(sn - kcp.snd_una)
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  func (kcp *KCP) parse_fastack(sn uint32) {
 | 
	
	
		
			
				|  | @@ -227,26 +219,11 @@ func (kcp *KCP) parse_fastack(sn uint32) {
 | 
	
		
			
				|  |  |  		return
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	for _, seg := range kcp.snd_buf {
 | 
	
		
			
				|  |  | -		if _itimediff(sn, seg.Number) < 0 {
 | 
	
		
			
				|  |  | -			break
 | 
	
		
			
				|  |  | -		} else if sn != seg.Number {
 | 
	
		
			
				|  |  | -			seg.ackSkipped++
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | +	kcp.snd_buf.HandleFastAck(sn)
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  func (kcp *KCP) HandleReceivingNext(receivingNext uint32) {
 | 
	
		
			
				|  |  | -	count := 0
 | 
	
		
			
				|  |  | -	for _, seg := range kcp.snd_buf {
 | 
	
		
			
				|  |  | -		if _itimediff(receivingNext, seg.Number) > 0 {
 | 
	
		
			
				|  |  | -			seg.Release()
 | 
	
		
			
				|  |  | -			count++
 | 
	
		
			
				|  |  | -		} else {
 | 
	
		
			
				|  |  | -			break
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	kcp.snd_buf = kcp.snd_buf[count:]
 | 
	
		
			
				|  |  | +	kcp.snd_buf.Clear(receivingNext)
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  func (kcp *KCP) HandleSendingNext(sendingNext uint32) {
 | 
	
	
		
			
				|  | @@ -362,7 +339,6 @@ func (kcp *KCP) flush() {
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	current := kcp.current
 | 
	
		
			
				|  |  | -	lost := false
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	// flush acknowledges
 | 
	
		
			
				|  |  |  	if kcp.acklist.Flush() {
 | 
	
	
		
			
				|  | @@ -385,47 +361,13 @@ func (kcp *KCP) flush() {
 | 
	
		
			
				|  |  |  		seg.timeout = current
 | 
	
		
			
				|  |  |  		seg.ackSkipped = 0
 | 
	
		
			
				|  |  |  		seg.transmit = 0
 | 
	
		
			
				|  |  | -		kcp.snd_buf = append(kcp.snd_buf, seg)
 | 
	
		
			
				|  |  | +		kcp.snd_buf.Push(seg)
 | 
	
		
			
				|  |  |  		kcp.snd_nxt++
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	// calculate resent
 | 
	
		
			
				|  |  | -	resent := uint32(kcp.fastresend)
 | 
	
		
			
				|  |  | -	if kcp.fastresend <= 0 {
 | 
	
		
			
				|  |  | -		resent = 0xffffffff
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  	// flush data segments
 | 
	
		
			
				|  |  | -	for _, segment := range kcp.snd_buf {
 | 
	
		
			
				|  |  | -		needsend := false
 | 
	
		
			
				|  |  | -		if segment.transmit == 0 {
 | 
	
		
			
				|  |  | -			needsend = true
 | 
	
		
			
				|  |  | -			segment.transmit++
 | 
	
		
			
				|  |  | -			segment.timeout = current + kcp.rx_rto
 | 
	
		
			
				|  |  | -		} else if _itimediff(current, segment.timeout) >= 0 {
 | 
	
		
			
				|  |  | -			needsend = true
 | 
	
		
			
				|  |  | -			segment.transmit++
 | 
	
		
			
				|  |  | -			segment.timeout = current + kcp.rx_rto
 | 
	
		
			
				|  |  | -			lost = true
 | 
	
		
			
				|  |  | -		} else if segment.ackSkipped >= resent {
 | 
	
		
			
				|  |  | -			needsend = true
 | 
	
		
			
				|  |  | -			segment.transmit++
 | 
	
		
			
				|  |  | -			segment.ackSkipped = 0
 | 
	
		
			
				|  |  | -			segment.timeout = current + kcp.rx_rto
 | 
	
		
			
				|  |  | -			lost = true
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		if needsend {
 | 
	
		
			
				|  |  | -			segment.Timestamp = current
 | 
	
		
			
				|  |  | -			segment.SendingNext = kcp.snd_una
 | 
	
		
			
				|  |  | -			segment.Opt = 0
 | 
	
		
			
				|  |  | -			if kcp.state == StateReadyToClose {
 | 
	
		
			
				|  |  | -				segment.Opt = SegmentOptionClose
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -			kcp.output.Write(segment)
 | 
	
		
			
				|  |  | -			kcp.sendingUpdated = false
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +	if kcp.snd_buf.Flush() {
 | 
	
		
			
				|  |  | +		kcp.sendingUpdated = false
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	if kcp.sendingUpdated || kcp.receivingUpdated || _itimediff(kcp.current, kcp.lastPingTime) >= 5000 {
 | 
	
	
		
			
				|  | @@ -447,18 +389,22 @@ func (kcp *KCP) flush() {
 | 
	
		
			
				|  |  |  	// flash remain segments
 | 
	
		
			
				|  |  |  	kcp.output.Flush()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	if kcp.congestionControl {
 | 
	
		
			
				|  |  | -		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
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +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
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -488,15 +434,10 @@ func (kcp *KCP) NoDelay(interval uint32, resend int, congestionControl bool) int
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // WaitSnd gets how many packet is waiting to be sent
 | 
	
		
			
				|  |  |  func (kcp *KCP) WaitSnd() uint32 {
 | 
	
		
			
				|  |  | -	return uint32(len(kcp.snd_buf)) + kcp.snd_queue.Len()
 | 
	
		
			
				|  |  | +	return uint32(kcp.snd_buf.Len()) + kcp.snd_queue.Len()
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  func (this *KCP) ClearSendQueue() {
 | 
	
		
			
				|  |  |  	this.snd_queue.Clear()
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	for _, seg := range this.snd_buf {
 | 
	
		
			
				|  |  | -		seg.Release()
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	this.snd_buf = nil
 | 
	
		
			
				|  |  | +	this.snd_buf.Clear(0xFFFFFFFF)
 | 
	
		
			
				|  |  |  }
 |