Propagate and log reason for connection close

This commit is contained in:
Jakob Borg 2013-12-30 21:21:57 -05:00
parent 7e3b29e3e0
commit 0f6b34160c
5 changed files with 43 additions and 30 deletions

View File

@ -188,11 +188,15 @@ func (m *Model) SeedIndex(fs []protocol.FileInfo) {
m.printModelStats() m.printModelStats()
} }
func (m *Model) Close(node string) { func (m *Model) Close(node string, err error) {
m.Lock() m.Lock()
defer m.Unlock() defer m.Unlock()
if err != nil {
warnf("Disconnected from node %s: %v", node, err)
} else {
infoln("Disconnected from node", node) infoln("Disconnected from node", node)
}
delete(m.remote, node) delete(m.remote, node)
delete(m.nodes, node) delete(m.nodes, node)

View File

@ -294,7 +294,7 @@ func TestForgetNode(t *testing.T) {
t.Errorf("Model len(need) incorrect (%d != %d)", l1, l2) t.Errorf("Model len(need) incorrect (%d != %d)", l1, l2)
} }
m.Close("42") m.Close("42", nil)
if l1, l2 := len(m.local), len(fs); l1 != l2 { if l1, l2 := len(m.local), len(fs); l1 != l2 {
t.Errorf("Model len(local) incorrect (%d != %d)", l1, l2) t.Errorf("Model len(local) incorrect (%d != %d)", l1, l2)

View File

@ -25,7 +25,7 @@ func (t *TestModel) Request(nodeID, name string, offset uint64, size uint32, has
return t.data, nil return t.data, nil
} }
func (t *TestModel) Close(nodeID string) { func (t *TestModel) Close(nodeID string, err error) {
t.closed = true t.closed = true
} }

View File

@ -3,8 +3,8 @@ package protocol
import ( import (
"compress/flate" "compress/flate"
"errors" "errors"
"fmt"
"io" "io"
"log"
"sync" "sync"
"time" "time"
@ -40,7 +40,7 @@ type Model interface {
// A request was made by the peer node // A request was made by the peer node
Request(nodeID, name string, offset uint64, size uint32, hash []byte) ([]byte, error) Request(nodeID, name string, offset uint64, size uint32, hash []byte) ([]byte, error)
// The peer node closed the connection // The peer node closed the connection
Close(nodeID string) Close(nodeID string, err error)
} }
type Connection struct { type Connection struct {
@ -130,8 +130,11 @@ func (c *Connection) Index(idx []FileInfo) {
err := c.flush() err := c.flush()
c.nextId = (c.nextId + 1) & 0xfff c.nextId = (c.nextId + 1) & 0xfff
c.Unlock() c.Unlock()
if err != nil || c.mwriter.err != nil { if err != nil {
c.Close() c.Close(err)
return
} else if c.mwriter.err != nil {
c.Close(c.mwriter.err)
return return
} }
} }
@ -149,13 +152,13 @@ func (c *Connection) Request(name string, offset uint64, size uint32, hash []byt
c.mwriter.writeRequest(request{name, offset, size, hash}) c.mwriter.writeRequest(request{name, offset, size, hash})
if c.mwriter.err != nil { if c.mwriter.err != nil {
c.Unlock() c.Unlock()
c.Close() c.Close(c.mwriter.err)
return nil, c.mwriter.err return nil, c.mwriter.err
} }
err := c.flush() err := c.flush()
if err != nil { if err != nil {
c.Unlock() c.Unlock()
c.Close() c.Close(err)
return nil, err return nil, err
} }
c.nextId = (c.nextId + 1) & 0xfff c.nextId = (c.nextId + 1) & 0xfff
@ -178,9 +181,13 @@ func (c *Connection) Ping() bool {
c.awaiting[c.nextId] = rc c.awaiting[c.nextId] = rc
c.mwriter.writeHeader(header{0, c.nextId, messageTypePing}) c.mwriter.writeHeader(header{0, c.nextId, messageTypePing})
err := c.flush() err := c.flush()
if err != nil || c.mwriter.err != nil { if err != nil {
c.Unlock() c.Unlock()
c.Close() c.Close(err)
return false
} else if c.mwriter.err != nil {
c.Unlock()
c.Close(c.mwriter.err)
return false return false
} }
c.nextId = (c.nextId + 1) & 0xfff c.nextId = (c.nextId + 1) & 0xfff
@ -204,7 +211,7 @@ func (c *Connection) flush() error {
return nil return nil
} }
func (c *Connection) Close() { func (c *Connection) Close(err error) {
c.Lock() c.Lock()
if c.closed { if c.closed {
c.Unlock() c.Unlock()
@ -217,7 +224,7 @@ func (c *Connection) Close() {
c.awaiting = nil c.awaiting = nil
c.Unlock() c.Unlock()
c.receiver.Close(c.ID) c.receiver.Close(c.ID, err)
} }
func (c *Connection) isClosed() bool { func (c *Connection) isClosed() bool {
@ -230,12 +237,11 @@ func (c *Connection) readerLoop() {
for !c.isClosed() { for !c.isClosed() {
hdr := c.mreader.readHeader() hdr := c.mreader.readHeader()
if c.mreader.err != nil { if c.mreader.err != nil {
c.Close() c.Close(c.mreader.err)
break break
} }
if hdr.version != 0 { if hdr.version != 0 {
log.Printf("Protocol error: %s: unknown message version %#x", c.ID, hdr.version) c.Close(fmt.Errorf("Protocol error: %s: unknown message version %#x", c.ID, hdr.version))
c.Close()
break break
} }
@ -247,7 +253,7 @@ func (c *Connection) readerLoop() {
case messageTypeIndex: case messageTypeIndex:
files := c.mreader.readIndex() files := c.mreader.readIndex()
if c.mreader.err != nil { if c.mreader.err != nil {
c.Close() c.Close(c.mreader.err)
} else { } else {
c.receiver.Index(c.ID, files) c.receiver.Index(c.ID, files)
} }
@ -255,7 +261,7 @@ func (c *Connection) readerLoop() {
case messageTypeIndexUpdate: case messageTypeIndexUpdate:
files := c.mreader.readIndex() files := c.mreader.readIndex()
if c.mreader.err != nil { if c.mreader.err != nil {
c.Close() c.Close(c.mreader.err)
} else { } else {
c.receiver.IndexUpdate(c.ID, files) c.receiver.IndexUpdate(c.ID, files)
} }
@ -267,7 +273,7 @@ func (c *Connection) readerLoop() {
data := c.mreader.readResponse() data := c.mreader.readResponse()
if c.mreader.err != nil { if c.mreader.err != nil {
c.Close() c.Close(c.mreader.err)
} else { } else {
c.Lock() c.Lock()
rc, ok := c.awaiting[hdr.msgID] rc, ok := c.awaiting[hdr.msgID]
@ -285,8 +291,10 @@ func (c *Connection) readerLoop() {
c.mwriter.writeUint32(encodeHeader(header{0, hdr.msgID, messageTypePong})) c.mwriter.writeUint32(encodeHeader(header{0, hdr.msgID, messageTypePong}))
err := c.flush() err := c.flush()
c.Unlock() c.Unlock()
if err != nil || c.mwriter.err != nil { if err != nil {
c.Close() c.Close(err)
} else if c.mwriter.err != nil {
c.Close(c.mwriter.err)
} }
case messageTypePong: case messageTypePong:
@ -304,8 +312,7 @@ func (c *Connection) readerLoop() {
} }
default: default:
log.Printf("Protocol error: %s: unknown message type %#x", c.ID, hdr.msgType) c.Close(fmt.Errorf("Protocol error: %s: unknown message type %#x", c.ID, hdr.msgType))
c.Close()
} }
} }
} }
@ -313,7 +320,7 @@ func (c *Connection) readerLoop() {
func (c *Connection) processRequest(msgID int) { func (c *Connection) processRequest(msgID int) {
req := c.mreader.readRequest() req := c.mreader.readRequest()
if c.mreader.err != nil { if c.mreader.err != nil {
c.Close() c.Close(c.mreader.err)
} else { } else {
go func() { go func() {
data, _ := c.receiver.Request(c.ID, req.name, req.offset, req.size, req.hash) data, _ := c.receiver.Request(c.ID, req.name, req.offset, req.size, req.hash)
@ -323,8 +330,10 @@ func (c *Connection) processRequest(msgID int) {
err := c.flush() err := c.flush()
c.Unlock() c.Unlock()
buffers.Put(data) buffers.Put(data)
if c.mwriter.err != nil || err != nil { if err != nil {
c.Close() c.Close(err)
} else if c.mwriter.err != nil {
c.Close(c.mwriter.err)
} }
}() }()
} }
@ -340,10 +349,10 @@ func (c *Connection) pingerLoop() {
select { select {
case ok := <-rc: case ok := <-rc:
if !ok { if !ok {
c.Close() c.Close(fmt.Errorf("Ping failure"))
} }
case <-time.After(pingTimeout): case <-time.After(pingTimeout):
c.Close() c.Close(fmt.Errorf("Ping timeout"))
} }
} }
} }

View File

@ -190,7 +190,7 @@ func TestClose(t *testing.T) {
c0 := NewConnection("c0", ar, bw, m0) c0 := NewConnection("c0", ar, bw, m0)
NewConnection("c1", br, aw, m1) NewConnection("c1", br, aw, m1)
c0.Close() c0.Close(nil)
ok := c0.isClosed() ok := c0.isClosed()
if !ok { if !ok {