committed by
Jakob Borg
parent
f35e1ac0c5
commit
ceea5ebeb3
14
vendor/github.com/xtaci/kcp-go/emitter.go
generated
vendored
14
vendor/github.com/xtaci/kcp-go/emitter.go
generated
vendored
@@ -7,17 +7,17 @@ import (
|
||||
|
||||
var defaultEmitter Emitter
|
||||
|
||||
const emitQueue = 8192
|
||||
|
||||
func init() {
|
||||
defaultEmitter.init()
|
||||
}
|
||||
|
||||
type (
|
||||
// packet emit request
|
||||
emitPacket struct {
|
||||
conn net.PacketConn
|
||||
to net.Addr
|
||||
data []byte
|
||||
conn net.PacketConn
|
||||
to net.Addr
|
||||
data []byte
|
||||
// mark this packet should recycle to global xmitBuf
|
||||
recycle bool
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ type (
|
||||
)
|
||||
|
||||
func (e *Emitter) init() {
|
||||
e.ch = make(chan emitPacket, emitQueue)
|
||||
e.ch = make(chan emitPacket)
|
||||
go e.emitTask()
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ func (e *Emitter) init() {
|
||||
func (e *Emitter) emitTask() {
|
||||
for p := range e.ch {
|
||||
if n, err := p.conn.WriteTo(p.data, p.to); err == nil {
|
||||
atomic.AddUint64(&DefaultSnmp.OutSegs, 1)
|
||||
atomic.AddUint64(&DefaultSnmp.OutPkts, 1)
|
||||
atomic.AddUint64(&DefaultSnmp.OutBytes, uint64(n))
|
||||
}
|
||||
if p.recycle {
|
||||
|
||||
19
vendor/github.com/xtaci/kcp-go/kcp.go
generated
vendored
19
vendor/github.com/xtaci/kcp-go/kcp.go
generated
vendored
@@ -117,6 +117,7 @@ func (seg *Segment) encode(ptr []byte) []byte {
|
||||
ptr = ikcp_encode32u(ptr, seg.sn)
|
||||
ptr = ikcp_encode32u(ptr, seg.una)
|
||||
ptr = ikcp_encode32u(ptr, uint32(len(seg.data)))
|
||||
atomic.AddUint64(&DefaultSnmp.OutSegs, 1)
|
||||
return ptr
|
||||
}
|
||||
|
||||
@@ -484,9 +485,10 @@ func (kcp *KCP) Input(data []byte, regular, ackNoDelay bool) int {
|
||||
}
|
||||
|
||||
var maxack uint32
|
||||
var lastackts uint32
|
||||
var flag int
|
||||
var inSegs uint64
|
||||
|
||||
current := currentMs()
|
||||
for {
|
||||
var ts, sn, length, una, conv uint32
|
||||
var wnd uint16
|
||||
@@ -525,10 +527,6 @@ func (kcp *KCP) Input(data []byte, regular, ackNoDelay bool) int {
|
||||
kcp.shrink_buf()
|
||||
|
||||
if cmd == IKCP_CMD_ACK {
|
||||
if _itimediff(current, ts) >= 0 {
|
||||
kcp.update_ack(_itimediff(current, ts))
|
||||
}
|
||||
|
||||
kcp.parse_ack(sn)
|
||||
kcp.shrink_buf()
|
||||
if flag == 0 {
|
||||
@@ -537,6 +535,7 @@ func (kcp *KCP) Input(data []byte, regular, ackNoDelay bool) int {
|
||||
} else if _itimediff(sn, maxack) > 0 {
|
||||
maxack = sn
|
||||
}
|
||||
lastackts = ts
|
||||
} else if cmd == IKCP_CMD_PUSH {
|
||||
if _itimediff(sn, kcp.rcv_nxt+kcp.rcv_wnd) < 0 {
|
||||
kcp.ack_push(sn, ts)
|
||||
@@ -567,11 +566,17 @@ func (kcp *KCP) Input(data []byte, regular, ackNoDelay bool) int {
|
||||
return -3
|
||||
}
|
||||
|
||||
inSegs++
|
||||
data = data[length:]
|
||||
}
|
||||
atomic.AddUint64(&DefaultSnmp.InSegs, inSegs)
|
||||
|
||||
if flag != 0 && regular {
|
||||
kcp.parse_fastack(maxack)
|
||||
current := currentMs()
|
||||
if _itimediff(current, lastackts) >= 0 {
|
||||
kcp.update_ack(_itimediff(current, lastackts))
|
||||
}
|
||||
}
|
||||
|
||||
if _itimediff(kcp.snd_una, una) > 0 {
|
||||
@@ -660,9 +665,9 @@ func (kcp *KCP) flush(ackOnly bool) {
|
||||
return
|
||||
}
|
||||
|
||||
current := currentMs()
|
||||
// probe window size (if remote window size equals zero)
|
||||
if kcp.rmt_wnd == 0 {
|
||||
current := currentMs()
|
||||
if kcp.probe_wait == 0 {
|
||||
kcp.probe_wait = IKCP_PROBE_INIT
|
||||
kcp.ts_probe = current + kcp.probe_wait
|
||||
@@ -742,6 +747,7 @@ func (kcp *KCP) flush(ackOnly bool) {
|
||||
|
||||
// send new segments
|
||||
for k := len(kcp.snd_buf) - newSegsCount; k < len(kcp.snd_buf); k++ {
|
||||
current := currentMs()
|
||||
segment := &kcp.snd_buf[k]
|
||||
segment.xmit++
|
||||
segment.rto = kcp.rx_rto
|
||||
@@ -765,6 +771,7 @@ func (kcp *KCP) flush(ackOnly bool) {
|
||||
|
||||
// check for retransmissions
|
||||
for k := 0; k < len(kcp.snd_buf)-newSegsCount; k++ {
|
||||
current := currentMs()
|
||||
segment := &kcp.snd_buf[k]
|
||||
needsend := false
|
||||
if _itimediff(current, segment.resendts) >= 0 { // RTO
|
||||
|
||||
140
vendor/github.com/xtaci/kcp-go/sess.go
generated
vendored
140
vendor/github.com/xtaci/kcp-go/sess.go
generated
vendored
@@ -23,13 +23,23 @@ func (errTimeout) Temporary() bool { return true }
|
||||
func (errTimeout) Error() string { return "i/o timeout" }
|
||||
|
||||
const (
|
||||
defaultWndSize = 128 // default window size, in packet
|
||||
nonceSize = 16 // magic number
|
||||
crcSize = 4 // 4bytes packet checksum
|
||||
// 16-bytes magic number for each packet
|
||||
nonceSize = 16
|
||||
|
||||
// 4-bytes packet checksum
|
||||
crcSize = 4
|
||||
|
||||
// overall crypto header size
|
||||
cryptHeaderSize = nonceSize + crcSize
|
||||
mtuLimit = 2048
|
||||
rxQueueLimit = 8192
|
||||
rxFECMulti = 3 // FEC keeps rxFECMulti* (dataShard+parityShard) ordered packets in memory
|
||||
|
||||
// maximum packet size
|
||||
mtuLimit = 2048
|
||||
|
||||
// packet receiving channel limit
|
||||
rxQueueLimit = 2048
|
||||
|
||||
// FEC keeps rxFECMulti* (dataShard+parityShard) ordered packets in memory
|
||||
rxFECMulti = 3
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -38,8 +48,12 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
// global packet buffer
|
||||
// shared among sending/receiving/FEC
|
||||
xmitBuf sync.Pool
|
||||
sid uint32
|
||||
|
||||
// monotonic session id
|
||||
sid uint32
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -51,36 +65,39 @@ func init() {
|
||||
type (
|
||||
// UDPSession defines a KCP session implemented by UDP
|
||||
UDPSession struct {
|
||||
// core
|
||||
sid uint32
|
||||
conn net.PacketConn // the underlying packet socket
|
||||
kcp *KCP // the core ARQ
|
||||
l *Listener // point to server listener if it's a server socket
|
||||
block BlockCrypt // encryption
|
||||
sockbuff []byte // kcp receiving is based on packet, I turn it into stream
|
||||
sid uint32 // session id(monotonic)
|
||||
conn net.PacketConn // the underlying packet connection
|
||||
kcp *KCP // KCP ARQ protocol
|
||||
l *Listener // point to the Listener if it's accepted by Listener
|
||||
block BlockCrypt // block encryption
|
||||
|
||||
// forward error correction
|
||||
fec *FEC
|
||||
fecDataShards [][]byte
|
||||
fecHeaderOffset int
|
||||
fecPayloadOffset int
|
||||
fecCnt int // count datashard
|
||||
fecMaxSize int // record maximum data length in datashard
|
||||
// kcp receiving is based on packets
|
||||
// sockbuff turns packets into stream
|
||||
sockbuff []byte
|
||||
|
||||
fec *FEC // forward error correction
|
||||
fecDataShards [][]byte // data shards cache
|
||||
fecShardCount int // count the number of datashards collected
|
||||
fecMaxSize int // record maximum data length in datashard
|
||||
|
||||
fecHeaderOffset int // FEC header offset in packet
|
||||
fecPayloadOffset int // FEC payload offset in packet
|
||||
|
||||
// settings
|
||||
remote net.Addr
|
||||
remote net.Addr // remote peer address
|
||||
rd time.Time // read deadline
|
||||
wd time.Time // write deadline
|
||||
headerSize int
|
||||
updateInterval int32
|
||||
ackNoDelay bool
|
||||
headerSize int // the overall header size added before KCP frame
|
||||
updateInterval int32 // interval in seconds to call kcp.flush()
|
||||
ackNoDelay bool // send ack immediately for each incoming packet
|
||||
|
||||
// notifications
|
||||
die chan struct{}
|
||||
chReadEvent chan struct{}
|
||||
chWriteEvent chan struct{}
|
||||
isClosed bool
|
||||
mu sync.Mutex
|
||||
die chan struct{} // notify session has Closed
|
||||
chReadEvent chan struct{} // notify Read() can be called without blocking
|
||||
chWriteEvent chan struct{} // notify Write() can be called without blocking
|
||||
|
||||
isClosed bool // flag the session has Closed
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
setReadBuffer interface {
|
||||
@@ -132,7 +149,6 @@ func newUDPSession(conv uint32, dataShards, parityShards int, l *Listener, conn
|
||||
sess.output(buf[:size])
|
||||
}
|
||||
})
|
||||
sess.kcp.WndSize(defaultWndSize, defaultWndSize)
|
||||
sess.kcp.SetMtu(IKCP_MTU_DEF - sess.headerSize)
|
||||
sess.kcp.setFEC(dataShards, parityShards)
|
||||
|
||||
@@ -324,11 +340,16 @@ func (s *UDPSession) SetWindowSize(sndwnd, rcvwnd int) {
|
||||
s.kcp.WndSize(sndwnd, rcvwnd)
|
||||
}
|
||||
|
||||
// SetMtu sets the maximum transmission unit
|
||||
func (s *UDPSession) SetMtu(mtu int) {
|
||||
// SetMtu sets the maximum transmission unit(not including UDP header)
|
||||
func (s *UDPSession) SetMtu(mtu int) bool {
|
||||
if mtu > mtuLimit {
|
||||
return false
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.kcp.SetMtu(mtu - s.headerSize)
|
||||
return true
|
||||
}
|
||||
|
||||
// SetStreamMode toggles the stream mode on/off
|
||||
@@ -416,9 +437,9 @@ func (s *UDPSession) output(buf []byte) {
|
||||
|
||||
// copy data to fec datashards
|
||||
sz := len(ext)
|
||||
s.fecDataShards[s.fecCnt] = s.fecDataShards[s.fecCnt][:sz]
|
||||
copy(s.fecDataShards[s.fecCnt], ext)
|
||||
s.fecCnt++
|
||||
s.fecDataShards[s.fecShardCount] = s.fecDataShards[s.fecShardCount][:sz]
|
||||
copy(s.fecDataShards[s.fecShardCount], ext)
|
||||
s.fecShardCount++
|
||||
|
||||
// record max datashard length
|
||||
if sz > s.fecMaxSize {
|
||||
@@ -426,7 +447,7 @@ func (s *UDPSession) output(buf []byte) {
|
||||
}
|
||||
|
||||
// calculate Reed-Solomon Erasure Code
|
||||
if s.fecCnt == s.fec.dataShards {
|
||||
if s.fecShardCount == s.fec.dataShards {
|
||||
// bzero each datashard's tail
|
||||
for i := 0; i < s.fec.dataShards; i++ {
|
||||
shard := s.fecDataShards[i]
|
||||
@@ -442,7 +463,7 @@ func (s *UDPSession) output(buf []byte) {
|
||||
}
|
||||
|
||||
// reset counters to zero
|
||||
s.fecCnt = 0
|
||||
s.fecShardCount = 0
|
||||
s.fecMaxSize = 0
|
||||
}
|
||||
}
|
||||
@@ -557,7 +578,7 @@ func (s *UDPSession) kcpInput(data []byte) {
|
||||
s.mu.Unlock()
|
||||
}
|
||||
|
||||
atomic.AddUint64(&DefaultSnmp.InSegs, 1)
|
||||
atomic.AddUint64(&DefaultSnmp.InPkts, 1)
|
||||
atomic.AddUint64(&DefaultSnmp.InBytes, uint64(len(data)))
|
||||
if fecParityShards > 0 {
|
||||
atomic.AddUint64(&DefaultSnmp.FECParityShards, fecParityShards)
|
||||
@@ -626,21 +647,23 @@ func (s *UDPSession) readLoop() {
|
||||
type (
|
||||
// Listener defines a server listening for connections
|
||||
Listener struct {
|
||||
block BlockCrypt
|
||||
dataShards, parityShards int
|
||||
fec *FEC // for fec init test
|
||||
conn net.PacketConn
|
||||
sessions map[string]*UDPSession
|
||||
chAccepts chan *UDPSession
|
||||
chDeadlinks chan net.Addr
|
||||
headerSize int
|
||||
die chan struct{}
|
||||
rxbuf sync.Pool
|
||||
rd atomic.Value
|
||||
wd atomic.Value
|
||||
block BlockCrypt // block encryption
|
||||
dataShards int // FEC data shard
|
||||
parityShards int // FEC parity shard
|
||||
fec *FEC // FEC mock initialization
|
||||
conn net.PacketConn // the underlying packet connection
|
||||
|
||||
sessions map[string]*UDPSession // all sessions accepted by this Listener
|
||||
chAccepts chan *UDPSession // Listen() backlog
|
||||
chDeadlinks chan net.Addr // session close queue
|
||||
headerSize int // the overall header size added before KCP frame
|
||||
die chan struct{} // notify the listener has closed
|
||||
rd atomic.Value // read deadline for Accept()
|
||||
wd atomic.Value
|
||||
}
|
||||
|
||||
packet struct {
|
||||
// incoming packet
|
||||
inPacket struct {
|
||||
from net.Addr
|
||||
data []byte
|
||||
}
|
||||
@@ -648,7 +671,7 @@ type (
|
||||
|
||||
// monitor incoming data for all connections of server
|
||||
func (l *Listener) monitor() {
|
||||
chPacket := make(chan packet, rxQueueLimit)
|
||||
chPacket := make(chan inPacket, rxQueueLimit)
|
||||
go l.receiver(chPacket)
|
||||
for {
|
||||
select {
|
||||
@@ -699,7 +722,7 @@ func (l *Listener) monitor() {
|
||||
}
|
||||
}
|
||||
|
||||
l.rxbuf.Put(raw)
|
||||
xmitBuf.Put(raw)
|
||||
case deadlink := <-l.chDeadlinks:
|
||||
delete(l.sessions, deadlink.String())
|
||||
case <-l.die:
|
||||
@@ -708,11 +731,11 @@ func (l *Listener) monitor() {
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Listener) receiver(ch chan packet) {
|
||||
func (l *Listener) receiver(ch chan inPacket) {
|
||||
for {
|
||||
data := l.rxbuf.Get().([]byte)[:mtuLimit]
|
||||
data := xmitBuf.Get().([]byte)[:mtuLimit]
|
||||
if n, from, err := l.conn.ReadFrom(data); err == nil && n >= l.headerSize+IKCP_OVERHEAD {
|
||||
ch <- packet{from, data[:n]}
|
||||
ch <- inPacket{from, data[:n]}
|
||||
} else if err != nil {
|
||||
return
|
||||
} else {
|
||||
@@ -829,9 +852,6 @@ func ServeConn(block BlockCrypt, dataShards, parityShards int, conn net.PacketCo
|
||||
l.parityShards = parityShards
|
||||
l.block = block
|
||||
l.fec = newFEC(rxFECMulti*(dataShards+parityShards), dataShards, parityShards)
|
||||
l.rxbuf.New = func() interface{} {
|
||||
return make([]byte, mtuLimit)
|
||||
}
|
||||
|
||||
// calculate header size
|
||||
if l.block != nil {
|
||||
|
||||
40
vendor/github.com/xtaci/kcp-go/snmp.go
generated
vendored
40
vendor/github.com/xtaci/kcp-go/snmp.go
generated
vendored
@@ -7,22 +7,24 @@ import (
|
||||
|
||||
// Snmp defines network statistics indicator
|
||||
type Snmp struct {
|
||||
BytesSent uint64 // raw bytes sent
|
||||
BytesReceived uint64
|
||||
MaxConn uint64
|
||||
ActiveOpens uint64
|
||||
PassiveOpens uint64
|
||||
CurrEstab uint64 // count of connections for now
|
||||
InErrs uint64 // udp read errors
|
||||
BytesSent uint64 // bytes sent from upper level
|
||||
BytesReceived uint64 // bytes received to upper level
|
||||
MaxConn uint64 // max number of connections ever reached
|
||||
ActiveOpens uint64 // accumulated active open connections
|
||||
PassiveOpens uint64 // accumulated passive open connections
|
||||
CurrEstab uint64 // current number of established connections
|
||||
InErrs uint64 // UDP read errors reported from net.PacketConn
|
||||
InCsumErrors uint64 // checksum errors from CRC32
|
||||
KCPInErrors uint64 // packet iput errors from kcp
|
||||
InSegs uint64
|
||||
OutSegs uint64
|
||||
InBytes uint64 // udp bytes received
|
||||
OutBytes uint64 // udp bytes sent
|
||||
RetransSegs uint64
|
||||
FastRetransSegs uint64
|
||||
EarlyRetransSegs uint64
|
||||
KCPInErrors uint64 // packet iput errors reported from KCP
|
||||
InPkts uint64 // incoming packets count
|
||||
OutPkts uint64 // outgoing packets count
|
||||
InSegs uint64 // incoming KCP segments
|
||||
OutSegs uint64 // outgoing KCP segments
|
||||
InBytes uint64 // UDP bytes received
|
||||
OutBytes uint64 // UDP bytes sent
|
||||
RetransSegs uint64 // accmulated retransmited segments
|
||||
FastRetransSegs uint64 // accmulated fast retransmitted segments
|
||||
EarlyRetransSegs uint64 // accmulated early retransmitted segments
|
||||
LostSegs uint64 // number of segs infered as lost
|
||||
RepeatSegs uint64 // number of segs duplicated
|
||||
FECRecovered uint64 // correct packets recovered from FEC
|
||||
@@ -47,6 +49,8 @@ func (s *Snmp) Header() []string {
|
||||
"InErrs",
|
||||
"InCsumErrors",
|
||||
"KCPInErrors",
|
||||
"InPkts",
|
||||
"OutPkts",
|
||||
"InSegs",
|
||||
"OutSegs",
|
||||
"InBytes",
|
||||
@@ -76,6 +80,8 @@ func (s *Snmp) ToSlice() []string {
|
||||
fmt.Sprint(snmp.InErrs),
|
||||
fmt.Sprint(snmp.InCsumErrors),
|
||||
fmt.Sprint(snmp.KCPInErrors),
|
||||
fmt.Sprint(snmp.InPkts),
|
||||
fmt.Sprint(snmp.OutPkts),
|
||||
fmt.Sprint(snmp.InSegs),
|
||||
fmt.Sprint(snmp.OutSegs),
|
||||
fmt.Sprint(snmp.InBytes),
|
||||
@@ -104,6 +110,8 @@ func (s *Snmp) Copy() *Snmp {
|
||||
d.InErrs = atomic.LoadUint64(&s.InErrs)
|
||||
d.InCsumErrors = atomic.LoadUint64(&s.InCsumErrors)
|
||||
d.KCPInErrors = atomic.LoadUint64(&s.KCPInErrors)
|
||||
d.InPkts = atomic.LoadUint64(&s.InPkts)
|
||||
d.OutPkts = atomic.LoadUint64(&s.OutPkts)
|
||||
d.InSegs = atomic.LoadUint64(&s.InSegs)
|
||||
d.OutSegs = atomic.LoadUint64(&s.OutSegs)
|
||||
d.InBytes = atomic.LoadUint64(&s.InBytes)
|
||||
@@ -131,6 +139,8 @@ func (s *Snmp) Reset() {
|
||||
atomic.StoreUint64(&s.InErrs, 0)
|
||||
atomic.StoreUint64(&s.InCsumErrors, 0)
|
||||
atomic.StoreUint64(&s.KCPInErrors, 0)
|
||||
atomic.StoreUint64(&s.InPkts, 0)
|
||||
atomic.StoreUint64(&s.OutPkts, 0)
|
||||
atomic.StoreUint64(&s.InSegs, 0)
|
||||
atomic.StoreUint64(&s.OutSegs, 0)
|
||||
atomic.StoreUint64(&s.InBytes, 0)
|
||||
|
||||
2
vendor/github.com/xtaci/kcp-go/updater.go
generated
vendored
2
vendor/github.com/xtaci/kcp-go/updater.go
generated
vendored
@@ -13,12 +13,14 @@ func init() {
|
||||
go updater.updateTask()
|
||||
}
|
||||
|
||||
// entry contains a session update info
|
||||
type entry struct {
|
||||
sid uint32
|
||||
ts time.Time
|
||||
s *UDPSession
|
||||
}
|
||||
|
||||
// a global heap managed kcp.flush() caller
|
||||
type updateHeap struct {
|
||||
entries []entry
|
||||
indices map[uint32]int
|
||||
|
||||
Reference in New Issue
Block a user