mirror of
https://github.com/octoleo/syncthing.git
synced 2024-12-22 19:08:58 +00:00
Ensure backwards compatibility before modifying protocol
This change makes sure that things work smoothly when "we" are a newer version than our peer and have more fields in our messages than they do. Missing fields will be left at zero/nil. (The other side will ignore our extra fields, for the same effect.)
This commit is contained in:
parent
2a58ca7697
commit
ce3e6e084c
2
Godeps/Godeps.json
generated
2
Godeps/Godeps.json
generated
@ -23,7 +23,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/calmh/xdr",
|
"ImportPath": "github.com/calmh/xdr",
|
||||||
"Rev": "45c46b7db7ff83b8b9ee09bbd95f36ab50043ece"
|
"Rev": "214788d8fedfc310c18eca9ed12be408a5054cd5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/juju/ratelimit",
|
"ImportPath": "github.com/juju/ratelimit",
|
||||||
|
4
Godeps/_workspace/src/github.com/calmh/xdr/reader.go
generated
vendored
4
Godeps/_workspace/src/github.com/calmh/xdr/reader.go
generated
vendored
@ -154,6 +154,10 @@ func (e XDRError) Error() string {
|
|||||||
return "xdr " + e.op + ": " + e.err.Error()
|
return "xdr " + e.op + ": " + e.err.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e XDRError) IsEOF() bool {
|
||||||
|
return e.err == io.EOF
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Reader) Error() error {
|
func (r *Reader) Error() error {
|
||||||
if r.err == nil {
|
if r.err == nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -133,6 +133,10 @@ type encodable interface {
|
|||||||
AppendXDR([]byte) ([]byte, error)
|
AppendXDR([]byte) ([]byte, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type isEofer interface {
|
||||||
|
IsEOF() bool
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
pingTimeout = 30 * time.Second
|
pingTimeout = 30 * time.Second
|
||||||
pingIdleTime = 60 * 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 {
|
switch hdr.msgType {
|
||||||
case messageTypeIndex, messageTypeIndexUpdate:
|
case messageTypeIndex, messageTypeIndexUpdate:
|
||||||
var idx IndexMessage
|
var idx IndexMessage
|
||||||
err = idx.UnmarshalXDR(msgBuf)
|
err = idx.UnmarshalXDR(msgBuf)
|
||||||
|
if xdrErr, ok := err.(isEofer); ok && xdrErr.IsEOF() {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
msg = idx
|
msg = idx
|
||||||
|
|
||||||
case messageTypeRequest:
|
case messageTypeRequest:
|
||||||
var req RequestMessage
|
var req RequestMessage
|
||||||
err = req.UnmarshalXDR(msgBuf)
|
err = req.UnmarshalXDR(msgBuf)
|
||||||
|
if xdrErr, ok := err.(isEofer); ok && xdrErr.IsEOF() {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
msg = req
|
msg = req
|
||||||
|
|
||||||
case messageTypeResponse:
|
case messageTypeResponse:
|
||||||
var resp ResponseMessage
|
var resp ResponseMessage
|
||||||
err = resp.UnmarshalXDR(msgBuf)
|
err = resp.UnmarshalXDR(msgBuf)
|
||||||
|
if xdrErr, ok := err.(isEofer); ok && xdrErr.IsEOF() {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
msg = resp
|
msg = resp
|
||||||
|
|
||||||
case messageTypePing, messageTypePong:
|
case messageTypePing, messageTypePong:
|
||||||
@ -398,11 +418,17 @@ func (c *rawConnection) readMessage() (hdr header, msg encodable, err error) {
|
|||||||
case messageTypeClusterConfig:
|
case messageTypeClusterConfig:
|
||||||
var cc ClusterConfigMessage
|
var cc ClusterConfigMessage
|
||||||
err = cc.UnmarshalXDR(msgBuf)
|
err = cc.UnmarshalXDR(msgBuf)
|
||||||
|
if xdrErr, ok := err.(isEofer); ok && xdrErr.IsEOF() {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
msg = cc
|
msg = cc
|
||||||
|
|
||||||
case messageTypeClose:
|
case messageTypeClose:
|
||||||
var cm CloseMessage
|
var cm CloseMessage
|
||||||
err = cm.UnmarshalXDR(msgBuf)
|
err = cm.UnmarshalXDR(msgBuf)
|
||||||
|
if xdrErr, ok := err.(isEofer); ok && xdrErr.IsEOF() {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
msg = cm
|
msg = cm
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
Loading…
Reference in New Issue
Block a user