From f82d957c9080a80caf8e58e28c195085b2ef1815 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 16 Jan 2017 18:03:34 -0800 Subject: [PATCH] lnwire+peer: introduce new error for unknown message type for forward compat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds a new error type to the `lnwire` package: `UnknownMessage`. With this error we can catch the particular case of a an error during reading that encounters a new or unknown message. When we encounter this message in the peer’s readHandler, we can now gracefully handle it by just skipping to the next message rather than closing out the section entirely. This puts us a bit closer to the spec, but not exactly as it has an additional constraint that we can only ignore a new message if it has an odd type. In a future release, we’ll modify this code to match the spec as written. --- lnwire/message.go | 19 +++++++++++++++++-- peer.go | 16 +++++++++++++++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/lnwire/message.go b/lnwire/message.go index 9eca6740c..79c71334c 100644 --- a/lnwire/message.go +++ b/lnwire/message.go @@ -57,6 +57,20 @@ const ( CmdPong = uint32(6010) ) +// UnknownMessage is an implementation of the error interface that allows the +// creation of an error in response to an unknown message. +type UnknownMessage struct { + messageType uint32 +} + +// Error returns a human readable string describing the error. +// +// This is part of the error interface. +func (u *UnknownMessage) Error() string { + return fmt.Sprintf("unable to parse message of unknown type: %v", + u.messageType) +} + // Message is an interface that defines a lightning wire protocol message. The // interface is general in order to allow implementing types full control over // the representation of its data. @@ -267,8 +281,9 @@ func ReadMessage(r io.Reader, pver uint32, btcnet wire.BitcoinNet) (int, Message msg, err := makeEmptyMessage(command) if err != nil { discardInput(r, hdr.length) - return totalBytes, nil, nil, fmt.Errorf("ReadMessage %s", - err.Error()) + return totalBytes, nil, nil, &UnknownMessage{ + messageType: command, + } } // Check for maximum length based on the message type. diff --git a/peer.go b/peer.go index 85a721ded..7e0bb45c1 100644 --- a/peer.go +++ b/peer.go @@ -360,7 +360,21 @@ out: nextMsg, _, err := p.readNextMessage() if err != nil { peerLog.Infof("unable to read message: %v", err) - break out + + switch err.(type) { + // If this is just a message we don't yet recognize, + // we'll continue processing as normal as this allows + // us to introduce new messages in a forwards + // compatible manner. + case *lnwire.UnknownMessage: + continue + + // If the error we encountered wasn't just a message we + // didn't recognize, then we'll stop all processing s + // this is a fatal error. + default: + break out + } } var isChanUpdate bool