| 
					
				 | 
			
			
				@@ -7,66 +7,36 @@ import ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 type ReceivingWindow struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	start uint32 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	size  uint32 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	list  []*DataSegment 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	cache map[uint32]*DataSegment 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func NewReceivingWindow(size uint32) *ReceivingWindow { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+func NewReceivingWindow() *ReceivingWindow { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	return &ReceivingWindow{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		start: 0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		size:  size, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		list:  make([]*DataSegment, size), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		cache: make(map[uint32]*DataSegment), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func (w *ReceivingWindow) Size() uint32 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return w.size 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func (w *ReceivingWindow) Position(idx uint32) (uint32, bool) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if idx >= w.size { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		return 0, false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return (w.start + idx) % w.size, true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func (w *ReceivingWindow) Set(idx uint32, value *DataSegment) bool { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	pos, ok := w.Position(idx) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if !ok { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		return false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if w.list[pos] != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+func (w *ReceivingWindow) Set(id uint32, value *DataSegment) bool { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	_, f := w.cache[id] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if f { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		return false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	w.list[pos] = value 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	w.cache[id] = value 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	return true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func (w *ReceivingWindow) Remove(idx uint32) *DataSegment { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	pos, ok := w.Position(idx) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if !ok { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		return nil 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	e := w.list[pos] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	w.list[pos] = nil 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return e 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func (w *ReceivingWindow) RemoveFirst() *DataSegment { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return w.Remove(0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func (w *ReceivingWindow) HasFirst() bool { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	pos, _ := w.Position(0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return w.list[pos] != nil 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+func (w *ReceivingWindow) Has(id uint32) bool { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	_, f := w.cache[id] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return f 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func (w *ReceivingWindow) Advance() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	w.start++ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if w.start == w.size { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		w.start = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+func (w *ReceivingWindow) Remove(id uint32) *DataSegment { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	v, f := w.cache[id] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if !f { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return nil 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	delete(w.cache, id) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return v 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 type AckList struct { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -167,15 +137,10 @@ type ReceivingWorker struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 func NewReceivingWorker(kcp *Connection) *ReceivingWorker { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	windowsSize := kcp.Config.GetReceivingInFlightSize() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if windowsSize > kcp.Config.GetReceivingBufferSize() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		windowsSize = kcp.Config.GetReceivingBufferSize() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	worker := &ReceivingWorker{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		conn:       kcp, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		window:     NewReceivingWindow(kcp.Config.GetReceivingBufferSize()), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		windowSize: windowsSize, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		window:     NewReceivingWindow(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		windowSize: kcp.Config.GetReceivingInFlightSize(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	worker.acklist = NewAckList(worker) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	return worker 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -206,7 +171,7 @@ func (w *ReceivingWorker) ProcessSegment(seg *DataSegment) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	w.acklist.Clear(seg.SendingNext) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	w.acklist.Add(number, seg.Timestamp) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if !w.window.Set(idx, seg) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if !w.window.Set(seg.Number, seg) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		seg.Release() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -223,11 +188,10 @@ func (w *ReceivingWorker) ReadMultiBuffer() buf.MultiBuffer { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	w.Lock() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	defer w.Unlock() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	for { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		seg := w.window.RemoveFirst() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		seg := w.window.Remove(w.nextNumber) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		if seg == nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			break 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		w.window.Advance() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		w.nextNumber++ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		mb.Append(seg.Detach()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		seg.Release() 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -248,7 +212,7 @@ func (w *ReceivingWorker) Read(b []byte) int { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 func (w *ReceivingWorker) IsDataAvailable() bool { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	w.RLock() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	defer w.RUnlock() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return w.window.HasFirst() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return w.window.Has(w.nextNumber) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 func (w *ReceivingWorker) NextNumber() uint32 { 
			 |