github.com/shaoyuan1943/gokcp@v0.0.0-20201026071748-5b36d4c87f61/kcp.go (about) 1 package gokcp 2 3 import ( 4 _ "unsafe" 5 ) 6 7 type segment struct { 8 convID uint32 9 cmd uint32 // package type 10 frg uint32 // user data slice number, 0 is last 11 wnd uint32 // recv window size 12 ts uint32 // send message timestamp 13 sn uint32 // sequence number 14 una uint32 // next message sequence number(recv) 15 resendTs uint32 // send time stamp 16 rto uint32 17 fastACK uint32 // skip ACK times 18 xmit uint32 19 dataBuffer []byte 20 acked bool // flag this segment ack incept 21 } 22 23 func (seg *segment) reset() { 24 seg.convID = 0 25 seg.cmd = 0 26 seg.frg = 0 27 seg.wnd = 0 28 seg.ts = 0 29 seg.sn = 0 30 seg.una = 0 31 seg.resendTs = 0 32 seg.rto = 0 33 seg.fastACK = 0 34 seg.xmit = 0 35 seg.dataBuffer = seg.dataBuffer[:0] 36 seg.acked = false 37 } 38 39 type KCP struct { 40 convID, mtu, mss, state uint32 41 lastACK uint32 42 sendUNA, sendNext, recvNext uint32 43 ssthresh uint32 44 rxRTTValue, rxSRTT, rxRTO, rxMinRTO int32 45 sendWnd, recvWnd, remoteWnd, cwnd uint32 46 interval, tsFlush, xmit uint32 47 noDelay bool 48 updated uint32 49 probe, tsProbe, probeWait uint32 50 deadLink, incr uint32 51 sendQueue, recvQueue []*segment 52 sendBuffer, recvBuffer []*segment 53 ackList []uint64 54 buffer *Buffer 55 fastResendACK, fastACKLimit uint32 56 nocwnd, streamMode bool 57 outputCallback OutputCallback 58 mdev, mdevMax, rttSN int32 59 stableNetwork bool 60 } 61 62 func NewKCP(convID uint32, outputCallbakc OutputCallback) *KCP { 63 kcp := &KCP{convID: convID, outputCallback: outputCallbakc} 64 kcp.sendWnd = KCP_WND_SND 65 kcp.recvWnd = KCP_WND_RCV 66 kcp.remoteWnd = KCP_WND_RCV 67 kcp.mtu = KCP_MTU_DEF 68 kcp.mss = kcp.mtu - KCP_OVERHEAD 69 kcp.rxRTO = int32(KCP_RTO_DEF) 70 kcp.rxMinRTO = int32(KCP_RTO_MIN) 71 kcp.interval = KCP_INTERVAL 72 kcp.tsFlush = KCP_INTERVAL 73 kcp.ssthresh = KCP_THRESH_INIT 74 kcp.fastACKLimit = KCP_FASTACK_LIMIT 75 kcp.deadLink = KCP_DEADLINK 76 77 return kcp 78 } 79 80 func (kcp *KCP) SetOutput(outputCallback OutputCallback) { 81 if outputCallback != nil { 82 kcp.outputCallback = outputCallback 83 } 84 } 85 86 // calculate a message data size 87 func (kcp *KCP) PeekSize() (size int) { 88 if len(kcp.recvQueue) <= 0 { 89 return 0 90 } 91 92 seg := kcp.recvQueue[0] 93 if seg.frg == 0 { 94 return len(seg.dataBuffer) 95 } 96 97 if len(kcp.recvQueue) < int(seg.frg+1) { 98 return 0 99 } 100 101 for idx := range kcp.recvQueue { 102 seg := kcp.recvQueue[idx] 103 size += len(seg.dataBuffer) 104 if seg.frg == 0 { 105 break 106 } 107 } 108 109 return 110 } 111 112 // read a whole message packet 113 // User or upper level recv: returns size, returns below zero for EAGAIN 114 func (kcp *KCP) Recv(buffer []byte) (int, error) { 115 if len(kcp.recvQueue) == 0 { 116 return 0, ErrNoReadableData 117 } 118 119 peekSize := kcp.PeekSize() 120 if peekSize <= 0 { 121 return 0, ErrNoReadableData 122 } 123 124 if peekSize > len(buffer) { 125 return 0, ErrNoEnoughSpace 126 } 127 128 isFastRecover := false 129 if len(kcp.recvQueue) >= int(kcp.recvWnd) { 130 isFastRecover = true 131 } 132 133 // merge fragment 134 n := 0 135 count := 0 136 for idx := range kcp.recvQueue { 137 seg := kcp.recvQueue[idx] 138 frg := seg.frg 139 copy(buffer[n:], seg.dataBuffer) 140 n += len(seg.dataBuffer) 141 count++ 142 143 putSegment(seg) 144 if frg == 0 { 145 break 146 } 147 } 148 149 if count > 0 { 150 kcp.recvQueue = removeFront(kcp.recvQueue, count) 151 } 152 153 // move seg from recvBuffer to recvQueue 154 count = 0 155 for idx := range kcp.recvBuffer { 156 seg := kcp.recvBuffer[idx] 157 if seg.sn == kcp.recvNext && len(kcp.recvQueue)+count < int(kcp.recvWnd) { 158 kcp.recvQueue = append(kcp.recvQueue, seg) 159 kcp.recvNext++ 160 count++ 161 } else { 162 break 163 } 164 } 165 166 if count > 0 { 167 kcp.recvBuffer = removeFront(kcp.recvBuffer, count) 168 } 169 170 // tell remote my recv window size, need to send KCP_CMD_WINS 171 if (len(kcp.recvQueue) < int(kcp.recvWnd)) && isFastRecover { 172 // ready to send back IKCP_CMD_WINS in ikcp_flush 173 // tell remote my window size in next 'flush' 174 kcp.probe |= KCP_ASK_TELL 175 } 176 177 return n, nil 178 } 179 180 func (kcp *KCP) Send(buffer []byte) error { 181 // append to previous segment in streaming mode (if possible) 182 if kcp.streamMode { 183 if len(kcp.sendQueue) > 0 { 184 seg := kcp.sendQueue[len(kcp.sendQueue)-1] 185 if len(seg.dataBuffer) < int(kcp.mss) { 186 capacity := int(kcp.mss) - len(seg.dataBuffer) 187 extend := 0 188 if len(buffer) < capacity { 189 extend = len(buffer) 190 } else { 191 extend = capacity 192 } 193 194 // copy data to old segment 195 orgLen := len(seg.dataBuffer) 196 seg.dataBuffer = seg.dataBuffer[:orgLen+extend] 197 copy(seg.dataBuffer[orgLen:], buffer) 198 buffer = buffer[extend:] 199 } 200 } 201 202 if len(buffer) == 0 { 203 return nil 204 } 205 } 206 207 count := 0 208 if len(buffer) <= (int)(kcp.mss) { 209 count = 1 210 } else { 211 count = (len(buffer) + int(kcp.mss) - 1) / int(kcp.mss) 212 } 213 214 if count >= int(KCP_WND_RCV) { 215 return ErrDataTooLong 216 } 217 218 if count == 0 { 219 count = 1 220 } 221 222 // slice data to fregment 223 for i := 0; i < count; i++ { 224 size := len(buffer) 225 if size > int(kcp.mss) { 226 size = int(kcp.mss) 227 } 228 229 seg := getSegment(kcp.mss) 230 seg.dataBuffer = seg.dataBuffer[:size] 231 copy(seg.dataBuffer, buffer[:size]) 232 if kcp.streamMode { 233 seg.frg = 0 234 } else { 235 seg.frg = uint32(count - i - 1) 236 } 237 238 kcp.sendQueue = append(kcp.sendQueue, seg) 239 buffer = buffer[size:] 240 } 241 242 return nil 243 } 244 245 func (kcp *KCP) updateACK(rtt int32) int32 { 246 if kcp.stableNetwork { 247 return kcp.updateACK2(rtt) 248 } 249 250 return kcp.updateACK1(rtt) 251 } 252 253 // calculate RTO 254 // RFC6298:http://tools.ietf.org/html/rfc6298 255 func (kcp *KCP) updateACK1(rtt int32) int32 { 256 if kcp.rxSRTT == 0 { 257 kcp.rxSRTT = rtt 258 kcp.rxRTTValue = rtt >> 1 // 1/2 259 } else { 260 delta := rtt - kcp.rxSRTT 261 if delta < 0 { 262 delta = -delta 263 } 264 265 kcp.rxRTTValue = (3*kcp.rxRTTValue + delta) / 4 // 1/4 266 kcp.rxSRTT = (7*kcp.rxSRTT + rtt) / 8 // 1/8 267 if kcp.rxSRTT < 1 { 268 kcp.rxSRTT = 1 269 } 270 } 271 272 rto := kcp.rxSRTT + int32(max(kcp.interval, uint32(4*kcp.rxRTTValue))) 273 kcp.rxRTO = int32(bound(uint32(kcp.rxMinRTO), uint32(rto), KCP_RTO_MAX)) 274 return kcp.rxRTO 275 } 276 277 // calculate RTO 278 // updateACK2 port from tcp_input.c 'tcp_rtt_estimator' function 279 // https://github.com/torvalds/linux/blob/master/net/ipv4/tcp_input.c 280 func (kcp *KCP) updateACK2(rtt int32) int32 { 281 srtt := kcp.rxSRTT 282 m := rtt 283 if kcp.rxSRTT == 0 { 284 srtt = m << 3 285 kcp.mdev = m << 1 // make sure rto = 3*rtt 286 kcp.rxRTTValue = int32(max(uint32(kcp.mdev), KCP_RTO_MIN)) 287 kcp.mdevMax = kcp.rxRTTValue 288 kcp.rttSN = int32(kcp.sendNext) 289 } else { 290 m -= srtt >> 3 291 srtt += m // rtt = 7/8 rtt + 1/8 new 292 if m < 0 { 293 m = -m // abs 294 m -= (kcp.mdev >> 2) 295 if m > 0 { 296 m >>= 3 297 } 298 } else { 299 m -= (kcp.mdev >> 2) 300 } 301 302 kcp.mdev += m // mdev = 3/4 mdev + 1/4 new 303 if kcp.mdev > kcp.mdevMax { 304 kcp.mdevMax = kcp.mdev 305 if kcp.mdevMax > kcp.rxRTTValue { 306 kcp.rxRTTValue = kcp.mdevMax 307 } 308 309 if int32(kcp.sendUNA) > kcp.rttSN { 310 if kcp.mdevMax < kcp.rxRTTValue { 311 kcp.rxRTTValue -= (kcp.rxRTTValue - kcp.mdevMax) >> 2 312 } 313 314 kcp.rttSN = int32(kcp.sendNext) 315 kcp.mdevMax = int32(KCP_RTO_MIN) 316 } 317 } 318 } 319 320 kcp.rxSRTT = int32(max(1, uint32(srtt))) 321 //rto := kcp.rxSRTT*1 + 4*kcp.mdev 322 rto := rtt + 4*kcp.mdev 323 kcp.rxRTO = int32(bound(uint32(kcp.rxMinRTO), uint32(rto), KCP_RTO_MAX)) 324 return kcp.rxRTO 325 } 326 327 func (kcp *KCP) setSendUNA() { 328 if len(kcp.sendBuffer) > 0 { 329 seg := kcp.sendBuffer[0] 330 kcp.sendUNA = seg.sn 331 } else { 332 kcp.sendUNA = kcp.sendNext 333 } 334 } 335 336 func (kcp *KCP) parseACK(sn uint32) { 337 if timediff(sn, kcp.sendUNA) < 0 || timediff(sn, kcp.sendNext) >= 0 { 338 return 339 } 340 341 for idx := range kcp.sendBuffer { 342 seg := kcp.sendBuffer[idx] 343 if sn == seg.sn { 344 seg.acked = true 345 break 346 } 347 348 if timediff(sn, seg.sn) < 0 { 349 break 350 } 351 } 352 } 353 354 func (kcp *KCP) parseUNA(una uint32) { 355 count := 0 356 for idx := range kcp.sendBuffer { 357 seg := kcp.sendBuffer[idx] 358 if timediff(una, seg.sn) > 0 { 359 putSegment(seg) 360 count++ 361 } else { 362 break 363 } 364 } 365 366 if count > 0 { 367 kcp.sendBuffer = removeFront(kcp.sendBuffer, count) 368 } 369 } 370 371 func (kcp *KCP) parseFastACK(sn uint32, ts uint32) { 372 if timediff(sn, kcp.sendUNA) < 0 || timediff(sn, kcp.sendNext) >= 0 { 373 return 374 } 375 376 for idx := range kcp.sendBuffer { 377 seg := kcp.sendBuffer[idx] 378 if timediff(sn, seg.sn) < 0 { 379 break 380 } else if sn != seg.sn { 381 if timediff(ts, seg.ts) >= 0 { 382 seg.fastACK++ 383 } 384 } 385 } 386 } 387 388 func (kcp *KCP) pushACK(sn, ts uint32) { 389 kcp.ackList = append(kcp.ackList, packACK(sn, ts)) 390 } 391 392 // Return true if this message has been received 393 func (kcp *KCP) parseData(newseg *segment) bool { 394 repeat := false 395 sn := newseg.sn 396 if timediff(sn, kcp.recvNext+kcp.recvWnd) >= 0 || timediff(sn, kcp.recvNext) < 0 { 397 return true 398 } 399 400 istIdx := 0 401 for idx := len(kcp.recvBuffer) - 1; idx >= 0; idx-- { 402 seg := kcp.recvBuffer[idx] 403 if seg.sn == sn { 404 // repeat message package 405 repeat = true 406 break 407 } 408 409 if timediff(sn, seg.sn) > 0 { 410 istIdx = idx + 1 411 break 412 } 413 } 414 415 if !repeat { 416 if istIdx == len(kcp.recvBuffer) { 417 kcp.recvBuffer = append(kcp.recvBuffer, newseg) 418 } else { 419 kcp.recvBuffer = append(kcp.recvBuffer, &segment{}) 420 copy(kcp.recvBuffer[istIdx+1:], kcp.recvBuffer[istIdx:]) 421 kcp.recvBuffer[istIdx] = newseg 422 } 423 } 424 425 // move available data from recvBuffer -> recvQueue 426 count := 0 427 for idx := range kcp.recvBuffer { 428 seg := kcp.recvBuffer[idx] 429 if seg.sn == kcp.recvNext && len(kcp.recvQueue) < int(kcp.recvWnd) { 430 count++ 431 kcp.recvNext++ 432 } else { 433 break 434 } 435 } 436 437 if count > 0 { 438 kcp.recvQueue = append(kcp.recvQueue, kcp.recvBuffer[:count]...) 439 kcp.recvBuffer = removeFront(kcp.recvBuffer, count) 440 } 441 return repeat 442 } 443 444 func (kcp *KCP) Input(data []byte) error { 445 prevUNA := kcp.sendUNA 446 var maxACK, latestACKTime uint32 = 0, 0 447 flag := 0 448 449 if len(data) < int(KCP_OVERHEAD) { 450 return ErrDataInvalid 451 } 452 453 currentTime := SetupFromNowMS() 454 for { 455 var ts, sn, length, una, convID uint32 456 var wnd uint16 457 var cmd, frg uint8 458 if len(data) < int(KCP_OVERHEAD) { 459 break 460 } 461 462 data = decode32u(data, &convID) 463 if convID != kcp.convID { 464 return ErrDifferenceConvID 465 } 466 467 data = decode8u(data, &cmd) 468 data = decode8u(data, &frg) 469 data = decode16u(data, &wnd) 470 data = decode32u(data, &ts) 471 data = decode32u(data, &sn) 472 data = decode32u(data, &una) 473 data = decode32u(data, &length) 474 475 if len(data) < int(length) || length < 0 { 476 return ErrDataInvalid 477 } 478 479 if uint32(cmd) != KCP_CMD_PUSH && uint32(cmd) != KCP_CMD_ACK && 480 uint32(cmd) != KCP_CMD_WASK && uint32(cmd) != KCP_CMD_WINS { 481 return ErrDataInvalid 482 } 483 484 kcp.remoteWnd = uint32(wnd) 485 kcp.parseUNA(una) 486 kcp.setSendUNA() 487 switch uint32(cmd) { 488 case KCP_CMD_ACK: 489 if timediff(currentTime, ts) >= 0 { 490 _ = kcp.updateACK(timediff(currentTime, ts)) 491 } 492 kcp.parseACK(sn) 493 kcp.setSendUNA() 494 495 if flag == 0 { 496 flag = 1 497 maxACK = sn 498 latestACKTime = ts 499 } else { 500 if timediff(sn, maxACK) > 0 { 501 maxACK = sn 502 latestACKTime = ts 503 } 504 } 505 case KCP_CMD_PUSH: 506 if timediff(sn, kcp.recvNext+kcp.recvWnd) < 0 { 507 kcp.pushACK(sn, ts) 508 if timediff(sn, kcp.recvNext) >= 0 { 509 seg := getSegment(kcp.mss) 510 seg.dataBuffer = seg.dataBuffer[:length] 511 seg.convID = convID 512 seg.cmd = uint32(cmd) 513 seg.frg = uint32(frg) 514 seg.wnd = uint32(wnd) 515 seg.ts = ts 516 seg.sn = sn 517 seg.una = una 518 repeat := kcp.parseData(seg) 519 if !repeat { 520 // delay copy 521 if length > 0 { 522 copy(seg.dataBuffer, data[:length]) 523 } 524 } else { 525 // repeat packet, throw it away 526 putSegment(seg) 527 } 528 } 529 } 530 case KCP_CMD_WASK: 531 // ready to send back IKCP_CMD_WINS in ikcp_flush 532 // tell remote my window size 533 kcp.probe |= KCP_ASK_TELL 534 case KCP_CMD_WINS: 535 // do nothing 536 default: 537 return ErrDataInvalid 538 } 539 540 data = data[length:] 541 } 542 543 if flag != 0 { 544 kcp.parseFastACK(maxACK, latestACKTime) 545 } 546 547 // update local cwnd 548 if timediff(kcp.sendUNA, prevUNA) > 0 { 549 if kcp.cwnd < kcp.remoteWnd { 550 mss := kcp.mss 551 if kcp.cwnd < kcp.ssthresh { 552 kcp.cwnd++ 553 kcp.incr += mss 554 } else { 555 if kcp.incr < mss { 556 kcp.incr = mss 557 } 558 559 // like tcp 560 kcp.incr += (mss*mss)/kcp.incr + (mss / 16) 561 if (kcp.cwnd+1)*mss <= kcp.incr { 562 var tmpVar uint32 = 1 563 if mss > 0 { 564 tmpVar = mss 565 } 566 kcp.cwnd = (kcp.incr + mss - 1) / tmpVar 567 } 568 } 569 570 if kcp.cwnd > kcp.remoteWnd { 571 kcp.cwnd = kcp.remoteWnd 572 kcp.incr = kcp.remoteWnd * mss 573 } 574 } 575 } 576 577 return nil 578 } 579 580 func (kcp *KCP) flush(isClose bool) error { 581 if kcp.updated == 0 { 582 return nil 583 } 584 585 currentTime := SetupFromNowMS() 586 seg := &segment{} 587 seg.convID = kcp.convID 588 seg.cmd = KCP_CMD_ACK 589 seg.frg = 0 590 // wnd unused 591 if uint32(len(kcp.recvQueue)) < kcp.recvWnd { 592 seg.wnd = kcp.recvWnd - uint32(len(kcp.recvQueue)) 593 } 594 seg.una = kcp.recvNext 595 seg.sn = 0 596 seg.ts = 0 597 598 if !isClose { 599 // flush acknowledges 600 for idx := range kcp.ackList { 601 if kcp.buffer.RawLen()+int(KCP_OVERHEAD) > int(kcp.mtu) { 602 err := kcp.outputCallback(kcp.buffer.RawData()) 603 if err != nil { 604 return err 605 } 606 607 kcp.buffer.Reset() 608 } 609 610 seg.sn, seg.ts = unpackACK(kcp.ackList[idx]) 611 kcp.buffer.WriteOverHeader(seg) 612 } 613 } 614 kcp.ackList = kcp.ackList[:0] 615 616 // probe window size (if remote window size equals zero) 617 if kcp.remoteWnd == 0 { 618 if kcp.probeWait == 0 { 619 kcp.probeWait = KCP_PROBE_INIT 620 kcp.tsProbe = currentTime + kcp.probeWait 621 } else { 622 if timediff(currentTime, kcp.probeWait) >= 0 { 623 if kcp.probeWait < KCP_PROBE_INIT { 624 kcp.probeWait = KCP_PROBE_INIT 625 } 626 kcp.probeWait += kcp.probeWait / 2 627 628 if kcp.probeWait > KCP_PROBE_LIMIT { 629 kcp.probeWait = KCP_PROBE_LIMIT 630 } 631 kcp.tsProbe = currentTime + kcp.probeWait 632 kcp.probe |= KCP_ASK_SEND 633 } 634 } 635 } else { 636 kcp.tsProbe = 0 637 kcp.probeWait = 0 638 } 639 640 if !isClose { 641 // flush window probing commands 642 if (kcp.probe & KCP_ASK_SEND) != 0 { 643 seg.cmd = KCP_CMD_WASK 644 if kcp.buffer.RawLen()+int(KCP_OVERHEAD) > int(kcp.mtu) { 645 err := kcp.outputCallback(kcp.buffer.RawData()) 646 if err != nil { 647 return err 648 } 649 kcp.buffer.Reset() 650 } 651 652 kcp.buffer.WriteOverHeader(seg) 653 } 654 655 if (kcp.probe & KCP_ASK_TELL) != 0 { 656 seg.cmd = KCP_CMD_WINS 657 if kcp.buffer.RawLen()+int(KCP_OVERHEAD) > int(kcp.mtu) { 658 err := kcp.outputCallback(kcp.buffer.RawData()) 659 if err != nil { 660 return err 661 } 662 kcp.buffer.Reset() 663 } 664 665 kcp.buffer.WriteOverHeader(seg) 666 } 667 kcp.probe = 0 668 } 669 670 // calculate window size 671 cwnd := min(kcp.sendWnd, kcp.remoteWnd) 672 if !kcp.nocwnd { 673 cwnd = min(kcp.cwnd, cwnd) 674 } 675 676 // move data from sendQueue to sendBuffer 677 count := 0 678 for idx := 0; idx < len(kcp.sendQueue); idx++ { 679 // flow control 680 // too many package are not ACKed maybe the net is crowd, so send this message next time 681 if timediff(kcp.sendNext, kcp.sendUNA+cwnd) >= 0 { 682 break 683 } 684 685 newseg := kcp.sendQueue[idx] 686 newseg.convID = kcp.convID 687 newseg.cmd = KCP_CMD_PUSH 688 newseg.wnd = seg.wnd 689 newseg.ts = currentTime 690 newseg.sn = kcp.sendNext 691 newseg.una = kcp.recvNext 692 newseg.resendTs = currentTime 693 newseg.rto = uint32(kcp.rxRTO) 694 newseg.fastACK = 0 695 newseg.xmit = 0 696 kcp.sendBuffer = append(kcp.sendBuffer, newseg) 697 kcp.sendNext++ 698 count++ 699 } 700 if count > 0 { 701 kcp.sendQueue = removeFront(kcp.sendQueue, count) 702 } 703 704 // calculate resent 705 var resent uint32 706 if kcp.fastResendACK > 0 { 707 resent = kcp.fastResendACK 708 } else { 709 resent = 0xFFFFFFFF 710 } 711 712 var minRTO uint32 713 if !kcp.noDelay { 714 minRTO = uint32(kcp.rxRTO >> 3) 715 } else { 716 minRTO = 0 717 } 718 719 // flush data segments 720 lost := false 721 change := 0 722 for idx := 0; idx < len(kcp.sendBuffer); idx++ { 723 sendSegment := kcp.sendBuffer[idx] 724 needSend := false 725 if sendSegment.acked { 726 continue 727 } 728 729 // first send 730 if sendSegment.xmit == 0 { 731 needSend = true 732 sendSegment.xmit++ 733 sendSegment.rto = uint32(kcp.rxRTO) 734 sendSegment.resendTs = currentTime + sendSegment.rto + minRTO 735 } else if timediff(currentTime, sendSegment.resendTs) >= 0 { 736 needSend = true 737 sendSegment.xmit++ 738 kcp.xmit++ 739 if !kcp.noDelay { 740 sendSegment.rto += uint32(kcp.rxRTO) 741 } else { 742 sendSegment.rto += uint32(kcp.rxRTO / 2) 743 } 744 sendSegment.resendTs = currentTime + sendSegment.rto 745 lost = true 746 } else if sendSegment.fastACK >= resent { 747 if sendSegment.xmit <= kcp.fastACKLimit || kcp.fastACKLimit <= 0 { 748 needSend = true 749 sendSegment.xmit++ 750 sendSegment.fastACK = 0 751 sendSegment.resendTs = currentTime + sendSegment.rto 752 change++ 753 } 754 } 755 756 if needSend { 757 sendSegment.ts = currentTime 758 sendSegment.wnd = seg.wnd 759 sendSegment.una = kcp.recvNext 760 761 if kcp.buffer.RawLen()+int(KCP_OVERHEAD)+len(sendSegment.dataBuffer) > int(kcp.mtu) { 762 err := kcp.outputCallback(kcp.buffer.RawData()) 763 if err != nil { 764 return err 765 } 766 kcp.buffer.Reset() 767 } 768 769 kcp.buffer.WriteOverHeader(sendSegment) 770 if len(sendSegment.dataBuffer) > 0 { 771 kcp.buffer.Write(sendSegment.dataBuffer) 772 } 773 774 if sendSegment.xmit >= kcp.deadLink { 775 kcp.state = 0xFFFFFFFF 776 } 777 } 778 } 779 780 // flash remain segments 781 if kcp.buffer.Len() > 0 { 782 err := kcp.outputCallback(kcp.buffer.RawData()) 783 if err != nil { 784 return err 785 } 786 kcp.buffer.Reset() 787 } 788 789 // update ssthresh 790 // rate halving, https://tools.ietf.org/html/rfc6937 791 if change > 0 { 792 inflight := kcp.sendNext - kcp.sendUNA 793 kcp.ssthresh = inflight / 2 794 if kcp.ssthresh < KCP_THRESH_MIN { 795 kcp.ssthresh = KCP_THRESH_MIN 796 } 797 kcp.cwnd = kcp.ssthresh + resent 798 kcp.incr = kcp.cwnd * kcp.mss 799 } 800 801 // if some package lost 802 if lost { 803 kcp.ssthresh = cwnd / 2 804 if kcp.ssthresh < KCP_THRESH_MIN { 805 kcp.ssthresh = KCP_THRESH_MIN 806 } 807 808 kcp.cwnd = 1 809 kcp.incr = kcp.mss 810 } 811 812 if kcp.cwnd < 1 { 813 kcp.cwnd = 1 814 kcp.incr = kcp.mss 815 } 816 817 return nil 818 } 819 820 //--------------------------------------------------------------------- 821 // update state (call it repeatedly, every 10ms-100ms), or you can ask 822 // 'Check' when to call it again (without Input/Send calling). 823 //--------------------------------------------------------------------- 824 func (kcp *KCP) Update() error { 825 currentTime := SetupFromNowMS() 826 if kcp.updated == 0 { 827 kcp.updated = 1 828 kcp.tsFlush = currentTime 829 } 830 831 slap := timediff(currentTime, kcp.tsFlush) 832 if slap >= 10000 || slap < -10000 { 833 kcp.tsFlush = currentTime 834 slap = 0 835 } 836 837 if slap >= 0 { 838 kcp.tsFlush += kcp.interval 839 if timediff(currentTime, kcp.tsFlush) >= 0 { 840 kcp.tsFlush = currentTime + kcp.interval 841 } 842 843 return kcp.flush(false) 844 } 845 846 return nil 847 } 848 849 func (kcp *KCP) SetBufferReserved(reserved int) bool { 850 if reserved < 0 || reserved >= int(kcp.mtu-KCP_OVERHEAD) { 851 return false 852 } 853 854 kcp.mss = kcp.mtu - KCP_OVERHEAD - uint32(reserved) 855 kcp.buffer = nil 856 kcp.buffer = NewBuffer(int(kcp.mtu), reserved) 857 return true 858 } 859 860 func (kcp *KCP) SetMTU(mtu int) bool { 861 if mtu < 50 || mtu < int(KCP_OVERHEAD) { 862 return false 863 } 864 865 kcp.mtu = uint32(mtu) 866 return true 867 } 868 869 func (kcp *KCP) SetInterval(interval int) { 870 if interval > 5000 { 871 interval = 5000 872 } else if interval < 5 { 873 interval = 5 874 } 875 876 kcp.interval = uint32(interval) 877 } 878 879 //--------------------------------------------------------------------- 880 // Determine when should you invoke Update: 881 // returns when you should invoke Update in millisec, if there 882 // is no Input/Send calling. you can call Update in that 883 // time, instead of call update repeatly. 884 885 // Important to reduce unnacessary Update invoking. use it to 886 // schedule Update (eg. implementing an epoll-like mechanism, 887 // or optimize Update when handling massive kcp connections) 888 // wiki: https://github.com/skywind3000/kcp/wiki/KCP-Best-Practice 889 //--------------------------------------------------------------------- 890 func (kcp *KCP) Check() uint32 { 891 currentTime := SetupFromNowMS() 892 if kcp.updated == 0 { 893 return currentTime 894 } 895 896 tsFlush := kcp.tsFlush 897 if timediff(currentTime, tsFlush) >= 10000 || timediff(currentTime, tsFlush) < -10000 { 898 tsFlush = currentTime 899 } 900 901 if timediff(currentTime, tsFlush) >= 0 { 902 return currentTime 903 } 904 905 tmPacket := 0x7FFFFFFF 906 tmFlush := 0x7FFFFFFF 907 minimal := 0 908 tsFlush = uint32(timediff(tsFlush, currentTime)) 909 for idx := range kcp.sendBuffer { 910 seg := kcp.sendBuffer[idx] 911 diff := timediff(seg.resendTs, currentTime) 912 if diff <= 0 { 913 return currentTime 914 } 915 if int(diff) < tmPacket { 916 tmPacket = int(diff) 917 } 918 } 919 920 if tmPacket < tmFlush { 921 minimal = tmPacket 922 } else { 923 minimal = tmFlush 924 } 925 926 if minimal >= int(kcp.interval) { 927 minimal = int(kcp.interval) 928 } 929 930 return currentTime + uint32(minimal) 931 } 932 933 func (kcp *KCP) SetNoDelay(noDelay bool, interval, resend int, nc bool) { 934 kcp.noDelay = noDelay 935 if kcp.noDelay { 936 kcp.rxMinRTO = int32(KCP_RTO_NDL) 937 } else { 938 kcp.rxMinRTO = int32(KCP_RTO_MIN) 939 } 940 941 kcp.SetInterval(interval) 942 kcp.fastResendACK = uint32(resend) 943 kcp.nocwnd = nc 944 } 945 946 func (kcp *KCP) SetWndSize(sendWnd, recvWnd int) { 947 kcp.sendWnd = uint32(sendWnd) 948 kcp.recvWnd = max(uint32(recvWnd), KCP_WND_RCV) 949 } 950 951 func (kcp *KCP) SendWnd() uint32 { 952 return kcp.sendWnd 953 } 954 955 func (kcp *KCP) RemoteWnd() uint32 { 956 return kcp.remoteWnd 957 } 958 959 func (kcp *KCP) WaitSend() int { 960 return len(kcp.sendQueue) + len(kcp.sendBuffer) 961 } 962 963 func (kcp *KCP) MTU() uint32 { 964 return kcp.mtu 965 } 966 967 func (kcp *KCP) MSS() uint32 { 968 return kcp.mss 969 } 970 971 func (kcp *KCP) SetStreamMode(streamMode bool) { 972 kcp.streamMode = streamMode 973 } 974 975 func (kcp *KCP) IsStreamMode() bool { 976 return kcp.streamMode 977 } 978 979 func (kcp *KCP) FlushWhenClosed() { 980 kcp.flush(true) 981 } 982 983 func (kcp *KCP) ConvID() uint32 { 984 return kcp.convID 985 } 986 987 func (kcp *KCP) RTO() int32 { 988 return kcp.rxRTO 989 } 990 991 type KCPStatus struct { 992 SendUNA int 993 SendNext int 994 RecvNext int 995 LastACK int 996 Threshold int 997 RTO int 998 FastResendACK int 999 FastACKLimit int 1000 SendWnd int 1001 RecvWnd int 1002 RemoteWnd int 1003 Wnd int 1004 SendQueueLen int 1005 SendBufferLen int 1006 RecvQueueLen int 1007 RecvBufferLen int 1008 ACKListLen int 1009 Incr int 1010 } 1011 1012 func (kcp *KCP) Snapshot(status *KCPStatus) { 1013 if status == nil { 1014 return 1015 } 1016 1017 status.SendUNA = int(kcp.sendUNA) 1018 status.SendNext = int(kcp.sendNext) 1019 status.RecvNext = int(kcp.recvNext) 1020 status.LastACK = int(kcp.lastACK) 1021 status.Threshold = int(kcp.ssthresh) 1022 status.RTO = int(kcp.rxRTO) 1023 status.FastResendACK = int(kcp.fastResendACK) 1024 status.FastACKLimit = int(kcp.fastACKLimit) 1025 status.SendWnd = int(kcp.sendWnd) 1026 status.RecvWnd = int(kcp.recvWnd) 1027 status.RemoteWnd = int(kcp.remoteWnd) 1028 status.Wnd = int(kcp.cwnd) 1029 status.SendQueueLen = len(kcp.sendQueue) 1030 status.SendBufferLen = len(kcp.sendBuffer) 1031 status.RecvQueueLen = len(kcp.recvQueue) 1032 status.RecvBufferLen = len(kcp.recvBuffer) 1033 status.ACKListLen = len(kcp.ackList) 1034 status.Incr = int(kcp.incr) 1035 }