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 }