eth, p2p: remove EncodeMsg from p2p.MsgWriter

...and make it a top-level function instead.

The original idea behind having EncodeMsg in the interface was that
implementations might be able to encode RLP data to their underlying
writer directly instead of buffering the encoded data. The encoder
will buffer anyway, so that doesn't matter anymore.

Given the recent problems with EncodeMsg (copy-pasted implementation
bug) I'd rather implement once, correctly.
This commit is contained in:
Felix Lange 2015-01-06 11:35:09 +01:00
parent 36e1e5f151
commit eb0e7b1b81
7 changed files with 25 additions and 31 deletions

View File

@ -140,7 +140,7 @@ func (self *ethProtocol) handle() error {
return self.protoError(ErrDecode, "->msg %v: %v", msg, err) return self.protoError(ErrDecode, "->msg %v: %v", msg, err)
} }
hashes := self.chainManager.GetBlockHashesFromHash(request.Hash, request.Amount) hashes := self.chainManager.GetBlockHashesFromHash(request.Hash, request.Amount)
return self.rw.EncodeMsg(BlockHashesMsg, ethutil.ByteSliceToInterface(hashes)...) return p2p.EncodeMsg(self.rw, BlockHashesMsg, ethutil.ByteSliceToInterface(hashes)...)
case BlockHashesMsg: case BlockHashesMsg:
// TODO: redo using lazy decode , this way very inefficient on known chains // TODO: redo using lazy decode , this way very inefficient on known chains
@ -185,7 +185,7 @@ func (self *ethProtocol) handle() error {
break break
} }
} }
return self.rw.EncodeMsg(BlocksMsg, blocks...) return p2p.EncodeMsg(self.rw, BlocksMsg, blocks...)
case BlocksMsg: case BlocksMsg:
msgStream := rlp.NewStream(msg.Payload) msgStream := rlp.NewStream(msg.Payload)
@ -298,12 +298,12 @@ func (self *ethProtocol) handleStatus() error {
func (self *ethProtocol) requestBlockHashes(from []byte) error { func (self *ethProtocol) requestBlockHashes(from []byte) error {
self.peer.Debugf("fetching hashes (%d) %x...\n", blockHashesBatchSize, from[0:4]) self.peer.Debugf("fetching hashes (%d) %x...\n", blockHashesBatchSize, from[0:4])
return self.rw.EncodeMsg(GetBlockHashesMsg, interface{}(from), uint64(blockHashesBatchSize)) return p2p.EncodeMsg(self.rw, GetBlockHashesMsg, interface{}(from), uint64(blockHashesBatchSize))
} }
func (self *ethProtocol) requestBlocks(hashes [][]byte) error { func (self *ethProtocol) requestBlocks(hashes [][]byte) error {
self.peer.Debugf("fetching %v blocks", len(hashes)) self.peer.Debugf("fetching %v blocks", len(hashes))
return self.rw.EncodeMsg(GetBlocksMsg, ethutil.ByteSliceToInterface(hashes)...) return p2p.EncodeMsg(self.rw, GetBlocksMsg, ethutil.ByteSliceToInterface(hashes)...)
} }
func (self *ethProtocol) protoError(code int, format string, params ...interface{}) (err *protocolError) { func (self *ethProtocol) protoError(code int, format string, params ...interface{}) (err *protocolError) {

View File

@ -41,10 +41,6 @@ func (self *testMsgReadWriter) WriteMsg(msg p2p.Msg) error {
return nil return nil
} }
func (self *testMsgReadWriter) EncodeMsg(code uint64, data ...interface{}) error {
return self.WriteMsg(p2p.NewMsg(code, data...))
}
func (self *testMsgReadWriter) ReadMsg() (p2p.Msg, error) { func (self *testMsgReadWriter) ReadMsg() (p2p.Msg, error) {
msg, ok := <-self.in msg, ok := <-self.in
if !ok { if !ok {

View File

@ -71,14 +71,11 @@ type MsgReader interface {
} }
type MsgWriter interface { type MsgWriter interface {
// WriteMsg sends an existing message. // WriteMsg sends a message. It will block until the message's
// The Payload reader of the message is consumed. // Payload has been consumed by the other end.
//
// Note that messages can be sent only once. // Note that messages can be sent only once.
WriteMsg(Msg) error WriteMsg(Msg) error
// EncodeMsg writes an RLP-encoded message with the given
// code and data elements.
EncodeMsg(code uint64, data ...interface{}) error
} }
// MsgReadWriter provides reading and writing of encoded messages. // MsgReadWriter provides reading and writing of encoded messages.
@ -87,6 +84,12 @@ type MsgReadWriter interface {
MsgWriter MsgWriter
} }
// EncodeMsg writes an RLP-encoded message with the given code and
// data elements.
func EncodeMsg(w MsgWriter, code uint64, data ...interface{}) error {
return w.WriteMsg(NewMsg(code, data...))
}
var magicToken = []byte{34, 64, 8, 145} var magicToken = []byte{34, 64, 8, 145}
func writeMsg(w io.Writer, msg Msg) error { func writeMsg(w io.Writer, msg Msg) error {
@ -209,11 +212,6 @@ func (p *MsgPipeRW) WriteMsg(msg Msg) error {
return ErrPipeClosed return ErrPipeClosed
} }
// EncodeMsg is a convenient shorthand for sending an RLP-encoded message.
func (p *MsgPipeRW) EncodeMsg(code uint64, data ...interface{}) error {
return p.WriteMsg(NewMsg(code, data...))
}
// ReadMsg returns a message sent on the other end of the pipe. // ReadMsg returns a message sent on the other end of the pipe.
func (p *MsgPipeRW) ReadMsg() (Msg, error) { func (p *MsgPipeRW) ReadMsg() (Msg, error) {
if atomic.LoadInt32(p.closed) == 0 { if atomic.LoadInt32(p.closed) == 0 {

View File

@ -75,8 +75,8 @@ func TestDecodeRealMsg(t *testing.T) {
func ExampleMsgPipe() { func ExampleMsgPipe() {
rw1, rw2 := MsgPipe() rw1, rw2 := MsgPipe()
go func() { go func() {
rw1.EncodeMsg(8, []byte{0, 0}) EncodeMsg(rw1, 8, []byte{0, 0})
rw1.EncodeMsg(5, []byte{1, 1}) EncodeMsg(rw1, 5, []byte{1, 1})
rw1.Close() rw1.Close()
}() }()
@ -100,7 +100,7 @@ loop:
rw1, rw2 := MsgPipe() rw1, rw2 := MsgPipe()
done := make(chan struct{}) done := make(chan struct{})
go func() { go func() {
if err := rw1.EncodeMsg(1); err == nil { if err := EncodeMsg(rw1, 1); err == nil {
t.Error("EncodeMsg returned nil error") t.Error("EncodeMsg returned nil error")
} else if err != ErrPipeClosed { } else if err != ErrPipeClosed {
t.Error("EncodeMsg returned wrong error: got %v, want %v", err, ErrPipeClosed) t.Error("EncodeMsg returned wrong error: got %v, want %v", err, ErrPipeClosed)

View File

@ -126,10 +126,10 @@ func TestPeerProtoEncodeMsg(t *testing.T) {
Name: "a", Name: "a",
Length: 2, Length: 2,
Run: func(peer *Peer, rw MsgReadWriter) error { Run: func(peer *Peer, rw MsgReadWriter) error {
if err := rw.EncodeMsg(2); err == nil { if err := EncodeMsg(rw, 2); err == nil {
t.Error("expected error for out-of-range msg code, got nil") t.Error("expected error for out-of-range msg code, got nil")
} }
if err := rw.EncodeMsg(1, "foo", "bar"); err != nil { if err := EncodeMsg(rw, 1, "foo", "bar"); err != nil {
t.Errorf("write error: %v", err) t.Errorf("write error: %v", err)
} }
return nil return nil

View File

@ -119,14 +119,14 @@ func (bp *baseProtocol) loop(quit <-chan error) error {
getPeersTick := time.NewTicker(10 * time.Second) getPeersTick := time.NewTicker(10 * time.Second)
defer getPeersTick.Stop() defer getPeersTick.Stop()
err := bp.rw.EncodeMsg(getPeersMsg) err := EncodeMsg(bp.rw, getPeersMsg)
for err == nil { for err == nil {
select { select {
case err = <-quit: case err = <-quit:
return err return err
case <-getPeersTick.C: case <-getPeersTick.C:
err = bp.rw.EncodeMsg(getPeersMsg) err = EncodeMsg(bp.rw, getPeersMsg)
case event := <-activity.Chan(): case event := <-activity.Chan():
ping.Reset(pingTimeout) ping.Reset(pingTimeout)
lastActive = event.(time.Time) lastActive = event.(time.Time)
@ -134,7 +134,7 @@ func (bp *baseProtocol) loop(quit <-chan error) error {
if lastActive.Add(pingTimeout * 2).Before(t) { if lastActive.Add(pingTimeout * 2).Before(t) {
err = newPeerError(errPingTimeout, "") err = newPeerError(errPingTimeout, "")
} else if lastActive.Add(pingTimeout).Before(t) { } else if lastActive.Add(pingTimeout).Before(t) {
err = bp.rw.EncodeMsg(pingMsg) err = EncodeMsg(bp.rw, pingMsg)
} }
} }
} }
@ -164,7 +164,7 @@ func (bp *baseProtocol) handle(rw MsgReadWriter) error {
return discRequestedError(reason[0]) return discRequestedError(reason[0])
case pingMsg: case pingMsg:
return bp.rw.EncodeMsg(pongMsg) return EncodeMsg(bp.rw, pongMsg)
case pongMsg: case pongMsg:
@ -177,7 +177,7 @@ func (bp *baseProtocol) handle(rw MsgReadWriter) error {
// //
// TODO: add event mechanism to notify baseProtocol for new peers // TODO: add event mechanism to notify baseProtocol for new peers
if len(peers) > 0 { if len(peers) > 0 {
return bp.rw.EncodeMsg(peersMsg, peers...) return EncodeMsg(bp.rw, peersMsg, peers...)
} }
case peersMsg: case peersMsg:

View File

@ -93,7 +93,7 @@ func TestBaseProtocolDisconnect(t *testing.T) {
if err := expectMsg(rw2, handshakeMsg); err != nil { if err := expectMsg(rw2, handshakeMsg); err != nil {
t.Error(err) t.Error(err)
} }
err := rw2.EncodeMsg(handshakeMsg, err := EncodeMsg(rw2, handshakeMsg,
baseProtocolVersion, baseProtocolVersion,
"", "",
[]interface{}{}, []interface{}{},
@ -106,7 +106,7 @@ func TestBaseProtocolDisconnect(t *testing.T) {
if err := expectMsg(rw2, getPeersMsg); err != nil { if err := expectMsg(rw2, getPeersMsg); err != nil {
t.Error(err) t.Error(err)
} }
if err := rw2.EncodeMsg(discMsg, DiscQuitting); err != nil { if err := EncodeMsg(rw2, discMsg, DiscQuitting); err != nil {
t.Error(err) t.Error(err)
} }