From 5110f80bba13e3758ae1836a88afee123df81e3e Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Fri, 13 Feb 2015 14:44:00 +0100 Subject: [PATCH] p2p: improve read deadlines There are now two deadlines, frameReadTimeout and payloadReadTimeout. The frame timeout is longer and allows for connections that are idle. The message timeout is still short and ensures that we don't get stuck in the middle of a message. --- p2p/message.go | 28 +++++++++++++++++++++++++--- p2p/peer.go | 14 ++------------ 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/p2p/message.go b/p2p/message.go index dfc33f349..07916f7b3 100644 --- a/p2p/message.go +++ b/p2p/message.go @@ -18,6 +18,28 @@ import ( "github.com/ethereum/go-ethereum/rlp" ) +// parameters for frameRW +const ( + // maximum time allowed for reading a message header. + // this is effectively the amount of time a connection can be idle. + frameReadTimeout = 1 * time.Minute + + // maximum time allowed for reading the payload data of a message. + // this is shorter than (and distinct from) frameReadTimeout because + // the connection is not considered idle while a message is transferred. + // this also limits the payload size of messages to how much the connection + // can transfer within the timeout. + payloadReadTimeout = 5 * time.Second + + // maximum amount of time allowed for writing a complete message. + msgWriteTimeout = 5 * time.Second + + // messages smaller than this many bytes will be read at + // once before passing them to a protocol. this increases + // concurrency in the processing. + wholePayloadSize = 64 * 1024 +) + // Msg defines the structure of a p2p message. // // Note that a Msg can only be sent once since the Payload reader is @@ -167,9 +189,7 @@ func makeListHeader(length uint32) []byte { func (rw *frameRW) ReadMsg() (msg Msg, err error) { <-rw.rsync // wait until bufconn is ours - // this read timeout applies also to the payload. - // TODO: proper read timeout - rw.SetReadDeadline(time.Now().Add(msgReadTimeout)) + rw.SetReadDeadline(time.Now().Add(frameReadTimeout)) // read magic and payload size start := make([]byte, 8) @@ -193,6 +213,8 @@ func (rw *frameRW) ReadMsg() (msg Msg, err error) { } msg.Size = size - posr.p + rw.SetReadDeadline(time.Now().Add(payloadReadTimeout)) + if msg.Size <= wholePayloadSize { // msg is small, read all of it and move on to the next message. pbuf := make([]byte, msg.Size) diff --git a/p2p/peer.go b/p2p/peer.go index b61cf96da..f779c1c02 100644 --- a/p2p/peer.go +++ b/p2p/peer.go @@ -15,22 +15,12 @@ import ( "github.com/ethereum/go-ethereum/rlp" ) -const ( - // maximum amount of time allowed for reading a message - msgReadTimeout = 5 * time.Second - // maximum amount of time allowed for writing a message - msgWriteTimeout = 5 * time.Second - // messages smaller than this many bytes will be read at - // once before passing them to a protocol. - wholePayloadSize = 64 * 1024 - - disconnectGracePeriod = 2 * time.Second -) - const ( baseProtocolVersion = 2 baseProtocolLength = uint64(16) baseProtocolMaxMsgSize = 10 * 1024 * 1024 + + disconnectGracePeriod = 2 * time.Second ) const (