don't time out a link unless we were expecting an ack and didn't get one

This commit is contained in:
Arceliar 2019-02-02 22:41:51 -06:00
parent b44a0f29f3
commit ebbe5f67ad

View File

@ -171,7 +171,7 @@ func (intf *linkInterface) handler() error {
go intf.peer.linkLoop() go intf.peer.linkLoop()
// Start the writer // Start the writer
signalReady := make(chan struct{}, 1) signalReady := make(chan struct{}, 1)
signalSent := make(chan struct{}, 1) signalSent := make(chan bool, 1)
sendAck := make(chan struct{}, 1) sendAck := make(chan struct{}, 1)
go func() { go func() {
defer close(signalReady) defer close(signalReady)
@ -182,7 +182,7 @@ func (intf *linkInterface) handler() error {
send := func(bs []byte) { send := func(bs []byte) {
intf.msgIO.writeMsg(bs) intf.msgIO.writeMsg(bs)
select { select {
case signalSent <- struct{}{}: case signalSent <- len(bs) > 0:
default: default:
} }
} }
@ -229,16 +229,15 @@ func (intf *linkInterface) handler() error {
go func() { go func() {
var isAlive bool var isAlive bool
var isReady bool var isReady bool
var ackTimerRunning bool var sendTimerRunning bool
timeout := 6 * time.Second // TODO set to ReadTimeout from the config, reset if it gets changed var recvTimerRunning bool
ackTime := time.Second recvTime := 6 * time.Second // TODO set to ReadTimeout from the config, reset if it gets changed
timer := time.NewTimer(timeout) sendTime := time.Second
defer util.TimerStop(timer) sendTimer := time.NewTimer(sendTime)
ackTimer := time.NewTimer(ackTime) defer util.TimerStop(sendTimer)
defer util.TimerStop(ackTimer) recvTimer := time.NewTimer(recvTime)
defer util.TimerStop(recvTimer)
for { for {
util.TimerStop(timer)
timer.Reset(timeout)
select { select {
case gotMsg, ok := <-signalAlive: case gotMsg, ok := <-signalAlive:
if !ok { if !ok {
@ -252,23 +251,26 @@ func (intf *linkInterface) handler() error {
intf.link.core.switchTable.idleIn <- intf.peer.port intf.link.core.switchTable.idleIn <- intf.peer.port
} }
} }
if gotMsg && !ackTimerRunning { if gotMsg && !sendTimerRunning {
util.TimerStop(ackTimer) // We got a message
ackTimer.Reset(ackTime) // Start a timer, if it expires then send a 0-sized ack to let them know we're alive
ackTimerRunning = true util.TimerStop(sendTimer)
sendTimer.Reset(sendTime)
sendTimerRunning = true
} }
case _, ok := <-signalSent: case sentMsg, ok := <-signalSent:
// Stop any running ack timer // Stop any running ack timer
if !ok { if !ok {
return return
} }
util.TimerStop(ackTimer) util.TimerStop(sendTimer)
ackTimerRunning = false sendTimerRunning = false
case <-ackTimer.C: if sentMsg && !recvTimerRunning {
// We haven't sent anything in the past ackTimeout, so signal a send of a nil packet // We sent a message
select { // Start a timer, if it expires and we haven't gotten any return traffic (including a 0-sized ack), then assume there's a problem
case sendAck <- struct{}{}: util.TimerStop(recvTimer)
default: recvTimer.Reset(recvTime)
recvTimerRunning = true
} }
case _, ok := <-signalReady: case _, ok := <-signalReady:
if !ok { if !ok {
@ -281,7 +283,14 @@ func (intf *linkInterface) handler() error {
// Keep enabled in the switch // Keep enabled in the switch
intf.link.core.switchTable.idleIn <- intf.peer.port intf.link.core.switchTable.idleIn <- intf.peer.port
} }
case <-timer.C: case <-sendTimer.C:
// We haven't sent anything, so signal a send of a 0 packet to let them know we're alive
select {
case sendAck <- struct{}{}:
default:
}
case <-recvTimer.C:
// We haven't received anything, so assume there's a problem and don't return this node to the switch until they start responding
isAlive = false isAlive = false
} }
} }