1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-10-01 16:26:02 -04:00

optimize ping and updater logic

This commit is contained in:
Darien Raymond 2016-10-11 12:24:19 +02:00
parent 78f87c4f60
commit f3a83c57ab
No known key found for this signature in database
GPG Key ID: 7251FFA14BB18169
3 changed files with 47 additions and 36 deletions

View File

@ -233,10 +233,11 @@ func NewConnection(conv uint16, writerCloser io.WriteCloser, local *net.UDPAddr,
}, },
conn.updateTask) conn.updateTask)
conn.pingUpdater = NewUpdater( conn.pingUpdater = NewUpdater(
3000, // 3 seconds 5000, // 5 seconds
func() bool { return conn.State() != StateTerminated }, func() bool { return conn.State() != StateTerminated },
func() bool { return conn.State() == StateTerminated }, func() bool { return conn.State() == StateTerminated },
conn.updateTask) conn.updateTask)
conn.pingUpdater.WakeUp()
return conn return conn
} }
@ -333,24 +334,22 @@ func (this *Connection) SetState(state State) {
switch state { switch state {
case StateReadyToClose: case StateReadyToClose:
this.receivingWorker.CloseRead() this.receivingWorker.CloseRead()
this.dataUpdater.WakeUp()
case StatePeerClosed: case StatePeerClosed:
this.sendingWorker.CloseWrite() this.sendingWorker.CloseWrite()
this.dataUpdater.WakeUp()
case StateTerminating: case StateTerminating:
this.receivingWorker.CloseRead() this.receivingWorker.CloseRead()
this.sendingWorker.CloseWrite() this.sendingWorker.CloseWrite()
this.dataUpdater.interval = time.Second this.pingUpdater.interval = time.Second
this.dataUpdater.WakeUp()
case StatePeerTerminating: case StatePeerTerminating:
this.sendingWorker.CloseWrite() this.sendingWorker.CloseWrite()
this.dataUpdater.WakeUp() this.pingUpdater.interval = time.Second
case StateTerminated: case StateTerminated:
this.receivingWorker.CloseRead() this.receivingWorker.CloseRead()
this.sendingWorker.CloseWrite() this.sendingWorker.CloseWrite()
this.dataUpdater.interval = time.Second this.pingUpdater.interval = time.Second
this.dataUpdater.WakeUp() this.dataUpdater.WakeUp()
this.Terminate() this.pingUpdater.WakeUp()
go this.Terminate()
} }
} }
@ -488,7 +487,6 @@ func (this *Connection) OnPeerClosed() {
func (this *Connection) Input(data []byte) int { func (this *Connection) Input(data []byte) int {
current := this.Elapsed() current := this.Elapsed()
atomic.StoreUint32(&this.lastIncomingTime, current) atomic.StoreUint32(&this.lastIncomingTime, current)
this.dataUpdater.WakeUp()
var seg Segment var seg Segment
for { for {
@ -502,10 +500,12 @@ func (this *Connection) Input(data []byte) int {
this.HandleOption(seg.Option) this.HandleOption(seg.Option)
this.receivingWorker.ProcessSegment(seg) this.receivingWorker.ProcessSegment(seg)
this.dataInputCond.Signal() this.dataInputCond.Signal()
this.dataUpdater.WakeUp()
case *AckSegment: case *AckSegment:
this.HandleOption(seg.Option) this.HandleOption(seg.Option)
this.sendingWorker.ProcessSegment(current, seg) this.sendingWorker.ProcessSegment(current, seg)
this.dataOutputCond.Signal() this.dataOutputCond.Signal()
this.dataUpdater.WakeUp()
case *CmdOnlySegment: case *CmdOnlySegment:
this.HandleOption(seg.Option) this.HandleOption(seg.Option)
if seg.Command == CommandTerminate { if seg.Command == CommandTerminate {
@ -545,12 +545,7 @@ func (this *Connection) flush() {
if this.State() == StateTerminating { if this.State() == StateTerminating {
log.Debug("KCP|Connection: #", this.conv, " sending terminating cmd.") log.Debug("KCP|Connection: #", this.conv, " sending terminating cmd.")
seg := NewCmdOnlySegment() this.Ping(current, CommandTerminate)
defer seg.Release()
seg.Conv = this.conv
seg.Command = CommandTerminate
this.output.Write(seg)
this.output.Flush() this.output.Flush()
if current-atomic.LoadUint32(&this.stateBeginTime) > 8000 { if current-atomic.LoadUint32(&this.stateBeginTime) > 8000 {
@ -570,19 +565,8 @@ func (this *Connection) flush() {
this.receivingWorker.Flush(current) this.receivingWorker.Flush(current)
this.sendingWorker.Flush(current) this.sendingWorker.Flush(current)
if current-atomic.LoadUint32(&this.lastPingTime) >= 3000 { if current-atomic.LoadUint32(&this.lastPingTime) >= 1000 {
seg := NewCmdOnlySegment() this.Ping(current, CommandPing)
seg.Conv = this.conv
seg.Command = CommandPing
seg.ReceivinNext = this.receivingWorker.nextNumber
seg.SendingNext = this.sendingWorker.firstUnacknowledged
seg.PeerRTO = this.roundTrip.Timeout()
if this.State() == StateReadyToClose {
seg.Option = SegmentOptionClose
}
this.output.Write(seg)
this.lastPingTime = current
seg.Release()
} }
// flash remain segments // flash remain segments
@ -592,3 +576,18 @@ func (this *Connection) flush() {
func (this *Connection) State() State { func (this *Connection) State() State {
return State(atomic.LoadInt32((*int32)(&this.state))) return State(atomic.LoadInt32((*int32)(&this.state)))
} }
func (this *Connection) Ping(current uint32, cmd Command) {
seg := NewCmdOnlySegment()
seg.Conv = this.conv
seg.Command = cmd
seg.ReceivinNext = this.receivingWorker.nextNumber
seg.SendingNext = this.sendingWorker.firstUnacknowledged
seg.PeerRTO = this.roundTrip.Timeout()
if this.State() == StateReadyToClose {
seg.Option = SegmentOptionClose
}
this.output.Write(seg)
atomic.StoreUint32(&this.lastPingTime, current)
seg.Release()
}

View File

@ -139,7 +139,10 @@ func (this *Listener) Accept() (internet.Connection, error) {
return nil, ErrClosedListener return nil, ErrClosedListener
} }
select { select {
case conn := <-this.awaitingConns: case conn, open := <-this.awaitingConns:
if !open {
break
}
if this.tlsConfig != nil { if this.tlsConfig != nil {
tlsConn := tls.Server(conn, this.tlsConfig) tlsConn := tls.Server(conn, this.tlsConfig)
return v2tls.NewConnection(tlsConn), nil return v2tls.NewConnection(tlsConn), nil

View File

@ -171,13 +171,14 @@ func (this *SendingWindow) Flush(current uint32, resend uint32, rto uint32, maxI
type SendingWorker struct { type SendingWorker struct {
sync.RWMutex sync.RWMutex
conn *Connection conn *Connection
window *SendingWindow window *SendingWindow
firstUnacknowledged uint32 firstUnacknowledged uint32
nextNumber uint32 firstUnacknowledgedUpdated bool
remoteNextNumber uint32 nextNumber uint32
controlWindow uint32 remoteNextNumber uint32
fastResend uint32 controlWindow uint32
fastResend uint32
} }
func NewSendingWorker(kcp *Connection) *SendingWorker { func NewSendingWorker(kcp *Connection) *SendingWorker {
@ -205,11 +206,15 @@ func (this *SendingWorker) ProcessReceivingNextWithoutLock(nextNumber uint32) {
// Private: Visible for testing. // Private: Visible for testing.
func (this *SendingWorker) FindFirstUnacknowledged() { func (this *SendingWorker) FindFirstUnacknowledged() {
v := this.firstUnacknowledged
if !this.window.IsEmpty() { if !this.window.IsEmpty() {
this.firstUnacknowledged = this.window.First().Number this.firstUnacknowledged = this.window.First().Number
} else { } else {
this.firstUnacknowledged = this.nextNumber this.firstUnacknowledged = this.nextNumber
} }
if v != this.firstUnacknowledged {
this.firstUnacknowledgedUpdated = true
}
} }
// Private: Visible for testing. // Private: Visible for testing.
@ -322,7 +327,11 @@ func (this *SendingWorker) Flush(current uint32) {
if !this.window.IsEmpty() { if !this.window.IsEmpty() {
this.window.Flush(current, this.conn.fastresend, this.conn.roundTrip.Timeout(), cwnd) this.window.Flush(current, this.conn.fastresend, this.conn.roundTrip.Timeout(), cwnd)
} else if this.firstUnacknowledgedUpdated {
this.conn.Ping(current, CommandPing)
} }
this.firstUnacknowledgedUpdated = false
} }
func (this *SendingWorker) CloseWrite() { func (this *SendingWorker) CloseWrite() {