Do ping check after 5 minute inactivity

This commit is contained in:
Jakob Borg 2013-12-15 16:19:45 +01:00
parent 768a7d5052
commit bef9ccfa71

View File

@ -5,6 +5,7 @@ import (
"errors" "errors"
"io" "io"
"sync" "sync"
"time"
"github.com/calmh/syncthing/buffers" "github.com/calmh/syncthing/buffers"
) )
@ -40,17 +41,19 @@ type Model interface {
} }
type Connection struct { type Connection struct {
receiver Model ID string
reader io.Reader receiver Model
mreader *marshalReader reader io.Reader
writer io.Writer mreader *marshalReader
mwriter *marshalWriter writer io.Writer
wLock sync.RWMutex mwriter *marshalWriter
closed bool wLock sync.RWMutex
closedLock sync.RWMutex closed bool
awaiting map[int]chan asyncResult closedLock sync.RWMutex
nextId int awaiting map[int]chan asyncResult
ID string nextId int
lastReceive time.Time
peerLatency time.Duration
} }
var ErrClosed = errors.New("Connection closed") var ErrClosed = errors.New("Connection closed")
@ -60,6 +63,9 @@ type asyncResult struct {
err error err error
} }
const pingTimeout = 30 * time.Second
const pingIdleTime = 5 * time.Minute
func NewConnection(nodeID string, reader io.Reader, writer io.Writer, receiver Model) *Connection { func NewConnection(nodeID string, reader io.Reader, writer io.Writer, receiver Model) *Connection {
flrd := flate.NewReader(reader) flrd := flate.NewReader(reader)
flwr, err := flate.NewWriter(writer, flate.BestSpeed) flwr, err := flate.NewWriter(writer, flate.BestSpeed)
@ -78,6 +84,7 @@ func NewConnection(nodeID string, reader io.Reader, writer io.Writer, receiver M
} }
go c.readerLoop() go c.readerLoop()
go c.pingerLoop()
return &c return &c
} }
@ -166,6 +173,10 @@ func (c *Connection) readerLoop() {
break break
} }
c.wLock.Lock()
c.lastReceive = time.Now()
c.wLock.Unlock()
switch hdr.msgType { switch hdr.msgType {
case messageTypeIndex: case messageTypeIndex:
files := c.mreader.readIndex() files := c.mreader.readIndex()
@ -237,3 +248,29 @@ func (c *Connection) processRequest(msgID int) {
}() }()
} }
} }
func (c *Connection) pingerLoop() {
var rc = make(chan time.Duration)
for !c.isClosed() {
c.wLock.RLock()
lr := c.lastReceive
c.wLock.RUnlock()
if time.Since(lr) > pingIdleTime {
go func() {
t0 := time.Now()
c.Ping()
rc <- time.Since(t0)
}()
select {
case lat := <-rc:
c.wLock.Lock()
c.peerLatency = (c.peerLatency + lat) / 2
c.wLock.Unlock()
case <-time.After(pingTimeout):
c.close()
}
}
time.Sleep(time.Second)
}
}