From 6286a39378e91ec8c92aeb44cb89985e548be640 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 9 May 2013 20:15:27 -0500 Subject: [PATCH] Combine readMessage with ReadMessage. These functions used to be split into multiple files, but since the code was reorganized there is no longer any reason to split them. --- internal_test.go | 6 --- message.go | 111 +++++++++++++++++++++------------------------- test_coverage.txt | 99 +++++++++++++++++++++-------------------- 3 files changed, 101 insertions(+), 115 deletions(-) diff --git a/internal_test.go b/internal_test.go index d57754a5..94b03f7b 100644 --- a/internal_test.go +++ b/internal_test.go @@ -87,12 +87,6 @@ func TstWriteBlockHeader(w io.Writer, pver uint32, bh *BlockHeader) error { return writeBlockHeader(w, pver, bh) } -// TstReadMessage makes the internal readMessage function available to -// the test package. -func TstReadMessage(r io.Reader, pver uint32, hdr *messageHeader) (Message, []byte, error) { - return readMessage(r, pver, hdr) -} - // TstReadMessageHeader makes the internal readMessageHeader function available // to the test package. func TstReadMessageHeader(r io.Reader) (*messageHeader, error) { diff --git a/message.go b/message.go index 8e107f1b..90afc844 100644 --- a/message.go +++ b/message.go @@ -160,64 +160,6 @@ func discardInput(r io.Reader, n uint32) { } } -// readMessage reads the next bitcoin message from r for the provided protocol -// version and message header. -func readMessage(r io.Reader, pver uint32, hdr *messageHeader) (Message, []byte, error) { - if hdr == nil { - return nil, nil, fmt.Errorf("readMessage: nil header") - } - - command := hdr.command - if !utf8.ValidString(command) { - discardInput(r, hdr.length) - str := "readMessage: invalid command %v" - return nil, nil, fmt.Errorf(str, []byte(command)) - } - - // Create struct of appropriate message type based on the command. - msg, err := makeEmptyMessage(command) - if err != nil { - discardInput(r, hdr.length) - return nil, nil, fmt.Errorf("readMessage: %v", err) - } - - // Check for maximum length based on the message type as a malicious client - // could otherwise create a well-formed header and set the length to max - // numbers in order to exhaust the machine's memory. - mpl := msg.MaxPayloadLength(pver) - if hdr.length > mpl { - discardInput(r, hdr.length) - str := "ReadMessage: payload exceeds max length - Header " + - "indicates %v bytes, but max payload size for messages of type " + - "[%v] is %v." - return nil, nil, fmt.Errorf(str, hdr.length, command, mpl) - } - - // Read payload. - payload := make([]byte, hdr.length) - _, err = io.ReadFull(r, payload) - if err != nil { - return nil, nil, err - } - - // Test checksum. - checksum := DoubleSha256(payload)[0:4] - if !bytes.Equal(checksum[:], hdr.checksum[:]) { - str := "readMessage: payload checksum failed - Header " + - "indicates %v, but actual checksum is %v." - return nil, nil, fmt.Errorf(str, hdr.checksum, checksum) - } - - // Unmarshal message. - pr := bytes.NewBuffer(payload) - err = msg.BtcDecode(pr, pver) - if err != nil { - return nil, nil, err - } - - return msg, payload, nil -} - // WriteMessage writes a bitcoin Message to w including the necessary header // information. func WriteMessage(w io.Writer, msg Message, pver uint32, btcnet BitcoinNet) error { @@ -271,7 +213,8 @@ func WriteMessage(w io.Writer, msg Message, pver uint32, btcnet BitcoinNet) erro return nil } -// ReadMessage reads, validates, and parses the next bitcoin Message from r. +// ReadMessage reads, validates, and parses the next bitcoin Message from r for +// the provided protocol version and bitcoin network. func ReadMessage(r io.Reader, pver uint32, btcnet BitcoinNet) (Message, []byte, error) { hdr, err := readMessageHeader(r) if err != nil { @@ -283,5 +226,53 @@ func ReadMessage(r io.Reader, pver uint32, btcnet BitcoinNet) (Message, []byte, return nil, nil, fmt.Errorf(str, hdr.magic) } - return readMessage(r, pver, hdr) + command := hdr.command + if !utf8.ValidString(command) { + discardInput(r, hdr.length) + str := "readMessage: invalid command %v" + return nil, nil, fmt.Errorf(str, []byte(command)) + } + + // Create struct of appropriate message type based on the command. + msg, err := makeEmptyMessage(command) + if err != nil { + discardInput(r, hdr.length) + return nil, nil, fmt.Errorf("readMessage: %v", err) + } + + // Check for maximum length based on the message type as a malicious client + // could otherwise create a well-formed header and set the length to max + // numbers in order to exhaust the machine's memory. + mpl := msg.MaxPayloadLength(pver) + if hdr.length > mpl { + discardInput(r, hdr.length) + str := "ReadMessage: payload exceeds max length - Header " + + "indicates %v bytes, but max payload size for messages of type " + + "[%v] is %v." + return nil, nil, fmt.Errorf(str, hdr.length, command, mpl) + } + + // Read payload. + payload := make([]byte, hdr.length) + _, err = io.ReadFull(r, payload) + if err != nil { + return nil, nil, err + } + + // Test checksum. + checksum := DoubleSha256(payload)[0:4] + if !bytes.Equal(checksum[:], hdr.checksum[:]) { + str := "readMessage: payload checksum failed - Header " + + "indicates %v, but actual checksum is %v." + return nil, nil, fmt.Errorf(str, hdr.checksum, checksum) + } + + // Unmarshal message. + pr := bytes.NewBuffer(payload) + err = msg.BtcDecode(pr, pver) + if err != nil { + return nil, nil, err + } + + return msg, payload, nil } diff --git a/test_coverage.txt b/test_coverage.txt index 3f776d33..6d62daef 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -5,50 +5,47 @@ github.com/conformal/btcwire/common.go writeVarInt 100.00% (16/16) github.com/conformal/btcwire/shahash.go NewShaHashFromStr 100.00% (15/15) github.com/conformal/btcwire/protocol.go ServiceFlag.String 100.00% (12/12) github.com/conformal/btcwire/common.go readVarString 100.00% (8/8) -github.com/conformal/btcwire/common.go randomUint64 100.00% (7/7) -github.com/conformal/btcwire/common.go DoubleSha256 100.00% (7/7) github.com/conformal/btcwire/msgversion.go NewMsgVersionFromConn 100.00% (7/7) github.com/conformal/btcwire/common.go writeVarString 100.00% (7/7) -github.com/conformal/btcwire/netaddress.go NewNetAddress 100.00% (5/5) +github.com/conformal/btcwire/common.go randomUint64 100.00% (7/7) +github.com/conformal/btcwire/common.go DoubleSha256 100.00% (7/7) +github.com/conformal/btcwire/msggetheaders.go MsgGetHeaders.AddBlockLocatorHash 100.00% (5/5) github.com/conformal/btcwire/msginv.go MsgInv.AddInvVect 100.00% (5/5) -github.com/conformal/btcwire/msgping.go MsgPing.BtcEncode 100.00% (5/5) -github.com/conformal/btcwire/msgping.go MsgPing.BtcDecode 100.00% (5/5) -github.com/conformal/btcwire/common.go writeElements 100.00% (5/5) github.com/conformal/btcwire/shahash.go ShaHash.SetBytes 100.00% (5/5) +github.com/conformal/btcwire/msgheaders.go MsgHeaders.AddBlockHeader 100.00% (5/5) +github.com/conformal/btcwire/netaddress.go NewNetAddress 100.00% (5/5) github.com/conformal/btcwire/msggetblocks.go MsgGetBlocks.AddBlockLocatorHash 100.00% (5/5) +github.com/conformal/btcwire/msggetdata.go MsgGetData.AddInvVect 100.00% (5/5) github.com/conformal/btcwire/msgaddr.go MsgAddr.AddAddress 100.00% (5/5) github.com/conformal/btcwire/msgaddr.go MsgAddr.AddAddresses 100.00% (5/5) -github.com/conformal/btcwire/msggetdata.go MsgGetData.AddInvVect 100.00% (5/5) +github.com/conformal/btcwire/common.go writeElements 100.00% (5/5) +github.com/conformal/btcwire/msgping.go MsgPing.BtcEncode 100.00% (5/5) +github.com/conformal/btcwire/msgping.go MsgPing.BtcDecode 100.00% (5/5) github.com/conformal/btcwire/msgnotfound.go MsgNotFound.AddInvVect 100.00% (5/5) -github.com/conformal/btcwire/msggetheaders.go MsgGetHeaders.AddBlockLocatorHash 100.00% (5/5) -github.com/conformal/btcwire/msgheaders.go MsgHeaders.AddBlockHeader 100.00% (5/5) github.com/conformal/btcwire/msgmempool.go MsgMemPool.BtcDecode 100.00% (4/4) -github.com/conformal/btcwire/netaddress.go maxNetAddressPayload 100.00% (4/4) github.com/conformal/btcwire/shahash.go ShaHash.String 100.00% (4/4) github.com/conformal/btcwire/msgmempool.go MsgMemPool.BtcEncode 100.00% (4/4) github.com/conformal/btcwire/msgpong.go MsgPong.MaxPayloadLength 100.00% (4/4) github.com/conformal/btcwire/msgping.go MsgPing.MaxPayloadLength 100.00% (4/4) -github.com/conformal/btcwire/msgaddr.go MsgAddr.MaxPayloadLength 100.00% (3/3) -github.com/conformal/btcwire/invvect.go InvType.String 100.00% (3/3) -github.com/conformal/btcwire/netaddress.go NetAddress.HasService 100.00% (3/3) -github.com/conformal/btcwire/msgblock.go MsgBlock.AddTransaction 100.00% (3/3) +github.com/conformal/btcwire/netaddress.go maxNetAddressPayload 100.00% (4/4) github.com/conformal/btcwire/shahash.go ShaHash.Bytes 100.00% (3/3) +github.com/conformal/btcwire/msgblock.go MsgBlock.AddTransaction 100.00% (3/3) +github.com/conformal/btcwire/msgaddr.go MsgAddr.MaxPayloadLength 100.00% (3/3) +github.com/conformal/btcwire/netaddress.go NetAddress.HasService 100.00% (3/3) github.com/conformal/btcwire/msgversion.go MsgVersion.HasService 100.00% (3/3) +github.com/conformal/btcwire/invvect.go InvType.String 100.00% (3/3) github.com/conformal/btcwire/netaddress.go NetAddress.SetAddress 100.00% (2/2) github.com/conformal/btcwire/msgblock.go MsgBlock.ClearTransactions 100.00% (2/2) -github.com/conformal/btcwire/msgverack.go MsgVerAck.BtcEncode 100.00% (1/1) -github.com/conformal/btcwire/msgverack.go MsgVerAck.BtcDecode 100.00% (1/1) +github.com/conformal/btcwire/msgalert.go MsgAlert.Command 100.00% (1/1) +github.com/conformal/btcwire/blockheader.go NewBlockHeader 100.00% (1/1) github.com/conformal/btcwire/common.go readElement 100.00% (1/1) github.com/conformal/btcwire/common.go writeElement 100.00% (1/1) github.com/conformal/btcwire/common.go RandomUint64 100.00% (1/1) github.com/conformal/btcwire/invvect.go NewInvVect 100.00% (1/1) -github.com/conformal/btcwire/msgalert.go MsgAlert.MaxPayloadLength 100.00% (1/1) -github.com/conformal/btcwire/shahash.go ShaHash.IsEqual 100.00% (1/1) github.com/conformal/btcwire/msgaddr.go MsgAddr.ClearAddresses 100.00% (1/1) github.com/conformal/btcwire/msgaddr.go MsgAddr.Command 100.00% (1/1) github.com/conformal/btcwire/msgaddr.go NewMsgAddr 100.00% (1/1) -github.com/conformal/btcwire/blockheader.go NewBlockHeader 100.00% (1/1) -github.com/conformal/btcwire/msgalert.go MsgAlert.Command 100.00% (1/1) +github.com/conformal/btcwire/msgalert.go MsgAlert.MaxPayloadLength 100.00% (1/1) github.com/conformal/btcwire/msgalert.go NewMsgAlert 100.00% (1/1) github.com/conformal/btcwire/msgblock.go MsgBlock.Command 100.00% (1/1) github.com/conformal/btcwire/msgblock.go MsgBlock.MaxPayloadLength 100.00% (1/1) @@ -59,19 +56,25 @@ github.com/conformal/btcwire/msggetaddr.go MsgGetAddr.BtcEncode 100.00% (1/1 github.com/conformal/btcwire/msggetaddr.go MsgGetAddr.Command 100.00% (1/1) github.com/conformal/btcwire/msggetaddr.go MsgGetAddr.MaxPayloadLength 100.00% (1/1) github.com/conformal/btcwire/msggetaddr.go NewMsgGetAddr 100.00% (1/1) -github.com/conformal/btcwire/netaddress.go NetAddress.AddService 100.00% (1/1) github.com/conformal/btcwire/msggetblocks.go MsgGetBlocks.Command 100.00% (1/1) github.com/conformal/btcwire/msggetblocks.go MsgGetBlocks.MaxPayloadLength 100.00% (1/1) github.com/conformal/btcwire/msggetblocks.go NewMsgGetBlocks 100.00% (1/1) github.com/conformal/btcwire/msggetdata.go MsgGetData.Command 100.00% (1/1) github.com/conformal/btcwire/msggetdata.go MsgGetData.MaxPayloadLength 100.00% (1/1) github.com/conformal/btcwire/msggetdata.go NewMsgGetData 100.00% (1/1) -github.com/conformal/btcwire/msgversion.go NewMsgVersion 100.00% (1/1) -github.com/conformal/btcwire/msgversion.go MsgVersion.MaxPayloadLength 100.00% (1/1) github.com/conformal/btcwire/msggetheaders.go MsgGetHeaders.Command 100.00% (1/1) github.com/conformal/btcwire/msggetheaders.go MsgGetHeaders.MaxPayloadLength 100.00% (1/1) github.com/conformal/btcwire/msggetheaders.go NewMsgGetHeaders 100.00% (1/1) -github.com/conformal/btcwire/msgversion.go MsgVersion.Command 100.00% (1/1) +github.com/conformal/btcwire/msgheaders.go MsgHeaders.Command 100.00% (1/1) +github.com/conformal/btcwire/msgheaders.go MsgHeaders.MaxPayloadLength 100.00% (1/1) +github.com/conformal/btcwire/msgheaders.go NewMsgHeaders 100.00% (1/1) +github.com/conformal/btcwire/msginv.go MsgInv.Command 100.00% (1/1) +github.com/conformal/btcwire/msginv.go MsgInv.MaxPayloadLength 100.00% (1/1) +github.com/conformal/btcwire/msginv.go NewMsgInv 100.00% (1/1) +github.com/conformal/btcwire/msgmempool.go MsgMemPool.Command 100.00% (1/1) +github.com/conformal/btcwire/msgmempool.go MsgMemPool.MaxPayloadLength 100.00% (1/1) +github.com/conformal/btcwire/msgmempool.go NewMsgMemPool 100.00% (1/1) +github.com/conformal/btcwire/msgnotfound.go MsgNotFound.Command 100.00% (1/1) github.com/conformal/btcwire/msgnotfound.go MsgNotFound.MaxPayloadLength 100.00% (1/1) github.com/conformal/btcwire/msgnotfound.go NewMsgNotFound 100.00% (1/1) github.com/conformal/btcwire/msgping.go MsgPing.Command 100.00% (1/1) @@ -83,28 +86,25 @@ github.com/conformal/btcwire/msgtx.go NewTxIn 100.00% (1/1) github.com/conformal/btcwire/msgtx.go NewTxOut 100.00% (1/1) github.com/conformal/btcwire/msgtx.go MsgTx.AddTxIn 100.00% (1/1) github.com/conformal/btcwire/msgtx.go MsgTx.AddTxOut 100.00% (1/1) -github.com/conformal/btcwire/msgverack.go MsgVerAck.Command 100.00% (1/1) github.com/conformal/btcwire/msgtx.go MsgTx.Command 100.00% (1/1) github.com/conformal/btcwire/msgtx.go MsgTx.MaxPayloadLength 100.00% (1/1) github.com/conformal/btcwire/msgtx.go NewMsgTx 100.00% (1/1) -github.com/conformal/btcwire/msgheaders.go MsgHeaders.Command 100.00% (1/1) -github.com/conformal/btcwire/msgheaders.go MsgHeaders.MaxPayloadLength 100.00% (1/1) -github.com/conformal/btcwire/msgheaders.go NewMsgHeaders 100.00% (1/1) -github.com/conformal/btcwire/msgversion.go MsgVersion.AddService 100.00% (1/1) -github.com/conformal/btcwire/msginv.go MsgInv.Command 100.00% (1/1) -github.com/conformal/btcwire/msginv.go MsgInv.MaxPayloadLength 100.00% (1/1) -github.com/conformal/btcwire/msginv.go NewMsgInv 100.00% (1/1) -github.com/conformal/btcwire/msgmempool.go MsgMemPool.Command 100.00% (1/1) -github.com/conformal/btcwire/msgmempool.go MsgMemPool.MaxPayloadLength 100.00% (1/1) -github.com/conformal/btcwire/msgmempool.go NewMsgMemPool 100.00% (1/1) -github.com/conformal/btcwire/msgverack.go NewMsgVerAck 100.00% (1/1) +github.com/conformal/btcwire/msgverack.go MsgVerAck.BtcDecode 100.00% (1/1) +github.com/conformal/btcwire/msgverack.go MsgVerAck.BtcEncode 100.00% (1/1) +github.com/conformal/btcwire/msgverack.go MsgVerAck.Command 100.00% (1/1) github.com/conformal/btcwire/msgverack.go MsgVerAck.MaxPayloadLength 100.00% (1/1) -github.com/conformal/btcwire/msgnotfound.go MsgNotFound.Command 100.00% (1/1) +github.com/conformal/btcwire/msgverack.go NewMsgVerAck 100.00% (1/1) +github.com/conformal/btcwire/msgversion.go MsgVersion.AddService 100.00% (1/1) +github.com/conformal/btcwire/msgversion.go MsgVersion.Command 100.00% (1/1) +github.com/conformal/btcwire/msgversion.go MsgVersion.MaxPayloadLength 100.00% (1/1) +github.com/conformal/btcwire/msgversion.go NewMsgVersion 100.00% (1/1) +github.com/conformal/btcwire/netaddress.go NetAddress.AddService 100.00% (1/1) +github.com/conformal/btcwire/shahash.go ShaHash.IsEqual 100.00% (1/1) github.com/conformal/btcwire/message.go makeEmptyMessage 95.00% (19/20) -github.com/conformal/btcwire/msgtx.go MsgTx.TxSha 85.71% (6/7) -github.com/conformal/btcwire/msgpong.go MsgPong.BtcDecode 85.71% (6/7) -github.com/conformal/btcwire/msgblock.go MsgBlock.TxShas 85.71% (6/7) github.com/conformal/btcwire/msgpong.go MsgPong.BtcEncode 85.71% (6/7) +github.com/conformal/btcwire/msgblock.go MsgBlock.TxShas 85.71% (6/7) +github.com/conformal/btcwire/msgpong.go MsgPong.BtcDecode 85.71% (6/7) +github.com/conformal/btcwire/msgtx.go MsgTx.TxSha 85.71% (6/7) github.com/conformal/btcwire/netaddress.go readNetAddress 85.00% (17/20) github.com/conformal/btcwire/blockheader.go readBlockHeader 80.00% (8/10) github.com/conformal/btcwire/msgblock.go MsgBlock.BtcDecode 80.00% (8/10) @@ -115,14 +115,14 @@ github.com/conformal/btcwire/msgblock.go MsgBlock.BtcEncode 77.78% (7/9) github.com/conformal/btcwire/msgtx.go readTxIn 76.47% (13/17) github.com/conformal/btcwire/msgtx.go MsgTx.BtcDecode 76.00% (19/25) github.com/conformal/btcwire/msgtx.go readTxOut 75.00% (9/12) -github.com/conformal/btcwire/blockheader.go BlockHeader.BlockSha 75.00% (6/8) -github.com/conformal/btcwire/blockheader.go writeBlockHeader 75.00% (6/8) github.com/conformal/btcwire/msgalert.go MsgAlert.BtcDecode 75.00% (6/8) +github.com/conformal/btcwire/blockheader.go BlockHeader.BlockSha 75.00% (6/8) github.com/conformal/btcwire/msgalert.go MsgAlert.BtcEncode 75.00% (6/8) -github.com/conformal/btcwire/invvect.go readInvVect 75.00% (3/4) +github.com/conformal/btcwire/blockheader.go writeBlockHeader 75.00% (6/8) github.com/conformal/btcwire/msgtx.go writeOutPoint 75.00% (3/4) -github.com/conformal/btcwire/msgtx.go readOutPoint 75.00% (3/4) +github.com/conformal/btcwire/invvect.go readInvVect 75.00% (3/4) github.com/conformal/btcwire/invvect.go writeInvVect 75.00% (3/4) +github.com/conformal/btcwire/msgtx.go readOutPoint 75.00% (3/4) github.com/conformal/btcwire/msgtx.go MsgTx.BtcEncode 73.91% (17/23) github.com/conformal/btcwire/msgtx.go writeTxIn 73.33% (11/15) github.com/conformal/btcwire/msgtx.go writeTxOut 72.73% (8/11) @@ -137,16 +137,17 @@ github.com/conformal/btcwire/msggetheaders.go MsgGetHeaders.BtcDecode 68.42% github.com/conformal/btcwire/msgversion.go MsgVersion.BtcDecode 68.00% (17/25) github.com/conformal/btcwire/msggetblocks.go MsgGetBlocks.BtcEncode 66.67% (12/18) github.com/conformal/btcwire/msggetheaders.go MsgGetHeaders.BtcEncode 66.67% (12/18) -github.com/conformal/btcwire/msggetdata.go MsgGetData.BtcEncode 66.67% (8/12) -github.com/conformal/btcwire/msgnotfound.go MsgNotFound.BtcEncode 66.67% (8/12) github.com/conformal/btcwire/msginv.go MsgInv.BtcEncode 66.67% (8/12) +github.com/conformal/btcwire/msgnotfound.go MsgNotFound.BtcEncode 66.67% (8/12) +github.com/conformal/btcwire/msggetdata.go MsgGetData.BtcEncode 66.67% (8/12) github.com/conformal/btcwire/msgversion.go MsgVersion.BtcEncode 63.64% (14/22) github.com/conformal/btcwire/msgheaders.go MsgHeaders.BtcDecode 62.50% (10/16) github.com/conformal/btcwire/msgaddr.go MsgAddr.BtcEncode 60.00% (9/15) github.com/conformal/btcwire/msgheaders.go MsgHeaders.BtcEncode 60.00% (9/15) -github.com/conformal/btcwire/message.go ReadMessage 57.14% (4/7) -github.com/conformal/btcwire/message.go readMessage 53.12% (17/32) +github.com/conformal/btcwire/message.go ReadMessage 54.55% (18/33) github.com/conformal/btcwire/msgblock.go MsgBlock.BtcDecodeTxLoc 0.00% (0/16) github.com/conformal/btcwire/message.go discardInput 0.00% (0/10) -github.com/conformal/btcwire --------------------------------- 78.69% (735/934) +github.com/conformal/btcwire/error.go MessageError.Error 0.00% (0/1) +github.com/conformal/btcwire/error.go messageError 0.00% (0/1) +github.com/conformal/btcwire --------------------------------- 78.71% (732/930)