From b44016ff70471793ff1ebb8ec37df395e159d9bc Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Wed, 28 May 2014 12:30:47 +0200 Subject: [PATCH] Don't ping timeout during long transfers (fixes #280) --- protocol/protocol.go | 20 ++++++++++++++++++-- xdr/reader.go | 18 ++++++++++++++---- xdr/writer.go | 22 +++++++++++++++++----- 3 files changed, 49 insertions(+), 11 deletions(-) diff --git a/protocol/protocol.go b/protocol/protocol.go index 442b185ab..9923b63e7 100644 --- a/protocol/protocol.go +++ b/protocol/protocol.go @@ -92,8 +92,8 @@ type asyncResult struct { } const ( - pingTimeout = 4 * time.Minute - pingIdleTime = 5 * time.Minute + pingTimeout = 300 * time.Second + pingIdleTime = 600 * time.Second ) func NewConnection(nodeID string, reader io.Reader, writer io.Writer, receiver Model) Connection { @@ -476,11 +476,27 @@ func (c *rawConnection) pingerLoop() { for { select { case <-ticker: + if d := time.Since(c.xr.LastRead()); d < pingIdleTime { + if debug { + l.Debugln(c.id, "ping skipped after rd", d) + } + continue + } + if d := time.Since(c.xw.LastWrite()); d < pingIdleTime { + if debug { + l.Debugln(c.id, "ping skipped after wr", d) + } + continue + } go func() { + if debug { + l.Debugln(c.id, "ping ->") + } rc <- c.ping() }() select { case ok := <-rc: + l.Debugln(c.id, "<- pong") if !ok { c.close(fmt.Errorf("ping failure")) } diff --git a/xdr/reader.go b/xdr/reader.go index bad58324b..f0f4b8822 100644 --- a/xdr/reader.go +++ b/xdr/reader.go @@ -3,15 +3,17 @@ package xdr import ( "errors" "io" + "time" ) var ErrElementSizeExceeded = errors.New("element size exceeded") type Reader struct { - r io.Reader - tot int - err error - b [8]byte + r io.Reader + tot int + err error + b [8]byte + last time.Time } func NewReader(r io.Reader) *Reader { @@ -44,6 +46,7 @@ func (r *Reader) ReadBytesMaxInto(max int, dst []byte) []byte { if r.err != nil { return nil } + r.last = time.Now() l := int(r.ReadUint32()) if r.err != nil { return nil @@ -74,6 +77,7 @@ func (r *Reader) ReadUint16() uint16 { if r.err != nil { return 0 } + r.last = time.Now() _, r.err = io.ReadFull(r.r, r.b[:4]) r.tot += 4 v := uint16(r.b[1]) | uint16(r.b[0])<<8 @@ -88,6 +92,7 @@ func (r *Reader) ReadUint32() uint32 { if r.err != nil { return 0 } + r.last = time.Now() n, r.err = io.ReadFull(r.r, r.b[:4]) if n < 4 { return 0 @@ -105,6 +110,7 @@ func (r *Reader) ReadUint64() uint64 { if r.err != nil { return 0 } + r.last = time.Now() n, r.err = io.ReadFull(r.r, r.b[:8]) r.tot += n v := uint64(r.b[7]) | uint64(r.b[6])<<8 | uint64(r.b[5])<<16 | uint64(r.b[4])<<24 | @@ -122,3 +128,7 @@ func (r *Reader) Tot() int { func (r *Reader) Error() error { return r.err } + +func (r *Reader) LastRead() time.Time { + return r.last +} diff --git a/xdr/writer.go b/xdr/writer.go index aae471218..a076410be 100644 --- a/xdr/writer.go +++ b/xdr/writer.go @@ -1,6 +1,9 @@ package xdr -import "io" +import ( + "io" + "time" +) func pad(l int) int { d := l % 4 @@ -13,10 +16,11 @@ func pad(l int) int { var padBytes = []byte{0, 0, 0} type Writer struct { - w io.Writer - tot int - err error - b [8]byte + w io.Writer + tot int + err error + b [8]byte + last time.Time } func NewWriter(w io.Writer) *Writer { @@ -34,6 +38,7 @@ func (w *Writer) WriteBytes(bs []byte) (int, error) { return 0, w.err } + w.last = time.Now() w.WriteUint32(uint32(len(bs))) if w.err != nil { return 0, w.err @@ -65,6 +70,7 @@ func (w *Writer) WriteUint16(v uint16) (int, error) { return 0, w.err } + w.last = time.Now() if debug { dl.Debugf("wr uint16=%d", v) } @@ -85,6 +91,7 @@ func (w *Writer) WriteUint32(v uint32) (int, error) { return 0, w.err } + w.last = time.Now() if debug { dl.Debugf("wr uint32=%d", v) } @@ -105,6 +112,7 @@ func (w *Writer) WriteUint64(v uint64) (int, error) { return 0, w.err } + w.last = time.Now() if debug { dl.Debugf("wr uint64=%d", v) } @@ -131,3 +139,7 @@ func (w *Writer) Tot() int { func (w *Writer) Error() error { return w.err } + +func (w *Writer) LastWrite() time.Time { + return w.last +}