|
|
@@ -32,25 +32,21 @@ type KCP struct {
|
|
|
lastIncomingTime uint32
|
|
|
lastPayloadTime uint32
|
|
|
sendingUpdated bool
|
|
|
- receivingUpdated bool
|
|
|
lastPingTime uint32
|
|
|
|
|
|
- mss uint32
|
|
|
- snd_una, snd_nxt, rcv_nxt uint32
|
|
|
- rx_rttvar, rx_srtt, rx_rto uint32
|
|
|
- snd_wnd, rcv_wnd, rmt_wnd, cwnd uint32
|
|
|
- current, interval 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
|
|
|
- rcv_queue *ReceivingQueue
|
|
|
- snd_buf *SendingWindow
|
|
|
- rcv_buf *ReceivingWindow
|
|
|
-
|
|
|
- acklist *AckList
|
|
|
+ snd_queue *SendingQueue
|
|
|
+ snd_buf *SendingWindow
|
|
|
+ receivingWorker *ReceivingWorker
|
|
|
|
|
|
fastresend int32
|
|
|
congestionControl bool
|
|
|
- output *SegmentWriter
|
|
|
+ output *BufferedSegmentWriter
|
|
|
}
|
|
|
|
|
|
// NewKCP create a new kcp control object, 'conv' must equal in two endpoint
|
|
|
@@ -60,18 +56,15 @@ func NewKCP(conv uint16, output *AuthenticationWriter) *KCP {
|
|
|
kcp := new(KCP)
|
|
|
kcp.conv = conv
|
|
|
kcp.snd_wnd = effectiveConfig.GetSendingWindowSize()
|
|
|
- kcp.rcv_wnd = effectiveConfig.GetReceivingWindowSize()
|
|
|
kcp.rmt_wnd = 32
|
|
|
kcp.mss = output.Mtu() - DataSegmentOverhead
|
|
|
kcp.rx_rto = 100
|
|
|
kcp.interval = effectiveConfig.Tti
|
|
|
kcp.output = NewSegmentWriter(output)
|
|
|
- kcp.rcv_buf = NewReceivingWindow(effectiveConfig.GetReceivingWindowSize())
|
|
|
kcp.snd_queue = NewSendingQueue(effectiveConfig.GetSendingQueueSize())
|
|
|
- kcp.rcv_queue = NewReceivingQueue()
|
|
|
- kcp.acklist = NewACKList(kcp)
|
|
|
kcp.snd_buf = NewSendingWindow(kcp, effectiveConfig.GetSendingWindowSize())
|
|
|
kcp.cwnd = kcp.snd_wnd
|
|
|
+ kcp.receivingWorker = NewReceivingWorker(kcp)
|
|
|
return kcp
|
|
|
}
|
|
|
|
|
|
@@ -81,13 +74,13 @@ func (kcp *KCP) SetState(state State) {
|
|
|
|
|
|
switch state {
|
|
|
case StateReadyToClose:
|
|
|
- kcp.rcv_queue.Close()
|
|
|
+ kcp.receivingWorker.CloseRead()
|
|
|
case StatePeerClosed:
|
|
|
kcp.ClearSendQueue()
|
|
|
case StateTerminating:
|
|
|
- kcp.rcv_queue.Close()
|
|
|
+ kcp.receivingWorker.CloseRead()
|
|
|
case StateTerminated:
|
|
|
- kcp.rcv_queue.Close()
|
|
|
+ kcp.receivingWorker.CloseRead()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -115,23 +108,6 @@ func (kcp *KCP) OnClose() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// DumpReceivingBuf moves available data from rcv_buf -> rcv_queue
|
|
|
-// @Private
|
|
|
-func (kcp *KCP) DumpReceivingBuf() {
|
|
|
- for {
|
|
|
- seg := kcp.rcv_buf.RemoveFirst()
|
|
|
- if seg == nil {
|
|
|
- break
|
|
|
- }
|
|
|
- kcp.rcv_queue.Put(seg.Data)
|
|
|
- seg.Data = nil
|
|
|
-
|
|
|
- kcp.rcv_buf.Advance()
|
|
|
- kcp.rcv_nxt++
|
|
|
- kcp.receivingUpdated = true
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
// Send is user/upper level send, returns below zero for error
|
|
|
func (kcp *KCP) Send(buffer []byte) int {
|
|
|
nBytes := 0
|
|
|
@@ -214,25 +190,6 @@ func (kcp *KCP) HandleReceivingNext(receivingNext uint32) {
|
|
|
kcp.snd_buf.Clear(receivingNext)
|
|
|
}
|
|
|
|
|
|
-func (kcp *KCP) HandleSendingNext(sendingNext uint32) {
|
|
|
- kcp.acklist.Clear(sendingNext)
|
|
|
-}
|
|
|
-
|
|
|
-func (kcp *KCP) parse_data(newseg *DataSegment) {
|
|
|
- sn := newseg.Number
|
|
|
- if _itimediff(sn, kcp.rcv_nxt+kcp.rcv_wnd) >= 0 ||
|
|
|
- _itimediff(sn, kcp.rcv_nxt) < 0 {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- idx := sn - kcp.rcv_nxt
|
|
|
- if !kcp.rcv_buf.Set(idx, newseg) {
|
|
|
- newseg.Release()
|
|
|
- }
|
|
|
-
|
|
|
- kcp.DumpReceivingBuf()
|
|
|
-}
|
|
|
-
|
|
|
// Input when you received a low level packet (eg. UDP packet), call it
|
|
|
func (kcp *KCP) Input(data []byte) int {
|
|
|
kcp.lastIncomingTime = kcp.current
|
|
|
@@ -249,10 +206,7 @@ func (kcp *KCP) Input(data []byte) int {
|
|
|
switch seg := seg.(type) {
|
|
|
case *DataSegment:
|
|
|
kcp.HandleOption(seg.Opt)
|
|
|
- kcp.HandleSendingNext(seg.SendingNext)
|
|
|
- kcp.acklist.Add(seg.Number, seg.Timestamp)
|
|
|
- kcp.receivingUpdated = true
|
|
|
- kcp.parse_data(seg)
|
|
|
+ kcp.receivingWorker.ProcessSegment(seg)
|
|
|
kcp.lastPayloadTime = kcp.current
|
|
|
case *ACKSegment:
|
|
|
kcp.HandleOption(seg.Opt)
|
|
|
@@ -288,7 +242,7 @@ func (kcp *KCP) Input(data []byte) int {
|
|
|
}
|
|
|
}
|
|
|
kcp.HandleReceivingNext(seg.ReceivinNext)
|
|
|
- kcp.HandleSendingNext(seg.SendingNext)
|
|
|
+ kcp.receivingWorker.ProcessSendingNext(seg.SendingNext)
|
|
|
kcp.shrink_buf()
|
|
|
default:
|
|
|
}
|
|
|
@@ -330,9 +284,7 @@ func (kcp *KCP) flush() {
|
|
|
current := kcp.current
|
|
|
|
|
|
// flush acknowledges
|
|
|
- if kcp.acklist.Flush() {
|
|
|
- kcp.receivingUpdated = false
|
|
|
- }
|
|
|
+ kcp.receivingWorker.Flush()
|
|
|
|
|
|
// calculate window size
|
|
|
cwnd := kcp.snd_una + kcp.snd_wnd
|
|
|
@@ -359,11 +311,11 @@ func (kcp *KCP) flush() {
|
|
|
kcp.sendingUpdated = false
|
|
|
}
|
|
|
|
|
|
- if kcp.sendingUpdated || kcp.receivingUpdated || _itimediff(kcp.current, kcp.lastPingTime) >= 5000 {
|
|
|
+ if kcp.sendingUpdated || kcp.receivingWorker.PingNecessary() || _itimediff(kcp.current, kcp.lastPingTime) >= 5000 {
|
|
|
seg := &CmdOnlySegment{
|
|
|
Conv: kcp.conv,
|
|
|
Cmd: SegmentCommandPing,
|
|
|
- ReceivinNext: kcp.rcv_nxt,
|
|
|
+ ReceivinNext: kcp.receivingWorker.nextNumber,
|
|
|
SendingNext: kcp.snd_una,
|
|
|
}
|
|
|
if kcp.state == StateReadyToClose {
|
|
|
@@ -372,7 +324,6 @@ func (kcp *KCP) flush() {
|
|
|
kcp.output.Write(seg)
|
|
|
kcp.lastPingTime = kcp.current
|
|
|
kcp.sendingUpdated = false
|
|
|
- kcp.receivingUpdated = false
|
|
|
}
|
|
|
|
|
|
// flash remain segments
|