diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 6c1f1821..cc336bf8 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -23,7 +23,7 @@ }, { "ImportPath": "github.com/calmh/xdr", - "Rev": "45c46b7db7ff83b8b9ee09bbd95f36ab50043ece" + "Rev": "214788d8fedfc310c18eca9ed12be408a5054cd5" }, { "ImportPath": "github.com/juju/ratelimit", diff --git a/Godeps/_workspace/src/github.com/calmh/xdr/reader.go b/Godeps/_workspace/src/github.com/calmh/xdr/reader.go index c21b9ce6..e669322c 100644 --- a/Godeps/_workspace/src/github.com/calmh/xdr/reader.go +++ b/Godeps/_workspace/src/github.com/calmh/xdr/reader.go @@ -154,6 +154,10 @@ func (e XDRError) Error() string { return "xdr " + e.op + ": " + e.err.Error() } +func (e XDRError) IsEOF() bool { + return e.err == io.EOF +} + func (r *Reader) Error() error { if r.err == nil { return nil diff --git a/internal/protocol/protocol.go b/internal/protocol/protocol.go index fb51a1c0..a6a4b8b4 100644 --- a/internal/protocol/protocol.go +++ b/internal/protocol/protocol.go @@ -133,6 +133,10 @@ type encodable interface { AppendXDR([]byte) ([]byte, error) } +type isEofer interface { + IsEOF() bool +} + const ( pingTimeout = 30 * time.Second pingIdleTime = 60 * time.Second @@ -376,20 +380,36 @@ func (c *rawConnection) readMessage() (hdr header, msg encodable, err error) { } } + // We check each returned error for the XDRError.IsEOF() method. + // IsEOF()==true here means that the message contained fewer fields than + // expected. It does not signify an EOF on the socket, because we've + // successfully read a size value and that many bytes already. New fields + // we expected but the other peer didn't send should be interpreted as + // zero/nil, and if that's not valid we'll verify it somewhere else. + switch hdr.msgType { case messageTypeIndex, messageTypeIndexUpdate: var idx IndexMessage err = idx.UnmarshalXDR(msgBuf) + if xdrErr, ok := err.(isEofer); ok && xdrErr.IsEOF() { + err = nil + } msg = idx case messageTypeRequest: var req RequestMessage err = req.UnmarshalXDR(msgBuf) + if xdrErr, ok := err.(isEofer); ok && xdrErr.IsEOF() { + err = nil + } msg = req case messageTypeResponse: var resp ResponseMessage err = resp.UnmarshalXDR(msgBuf) + if xdrErr, ok := err.(isEofer); ok && xdrErr.IsEOF() { + err = nil + } msg = resp case messageTypePing, messageTypePong: @@ -398,11 +418,17 @@ func (c *rawConnection) readMessage() (hdr header, msg encodable, err error) { case messageTypeClusterConfig: var cc ClusterConfigMessage err = cc.UnmarshalXDR(msgBuf) + if xdrErr, ok := err.(isEofer); ok && xdrErr.IsEOF() { + err = nil + } msg = cc case messageTypeClose: var cm CloseMessage err = cm.UnmarshalXDR(msgBuf) + if xdrErr, ok := err.(isEofer); ok && xdrErr.IsEOF() { + err = nil + } msg = cm default: