Skip to content

Commit 5ba5159

Browse files
committed
p2p: use package rlp to encode messages
Message encoding functions have been renamed to catch any uses. The switch to the new encoder can cause subtle incompatibilities. If there are any users outside of our tree, they will at least be alerted that there was a change. NewMsg no longer exists. The replacements for EncodeMsg are called Send and SendItems.
1 parent 4811f46 commit 5ba5159

File tree

8 files changed

+64
-68
lines changed

8 files changed

+64
-68
lines changed

p2p/handshake.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ func setupInboundConn(fd net.Conn, prv *ecdsa.PrivateKey, our *protoHandshake) (
9292
return nil, errors.New("node ID in protocol handshake does not match encryption handshake")
9393
}
9494
// TODO: validate that handshake node ID matches
95-
if err := writeProtocolHandshake(rw, our); err != nil {
95+
if err := Send(rw, handshakeMsg, our); err != nil {
9696
return nil, fmt.Errorf("protocol write error: %v", err)
9797
}
9898
return &conn{rw, rhs}, nil
@@ -106,7 +106,7 @@ func setupOutboundConn(fd net.Conn, prv *ecdsa.PrivateKey, our *protoHandshake,
106106

107107
// Run the protocol handshake using authenticated messages.
108108
rw := newRlpxFrameRW(fd, secrets)
109-
if err := writeProtocolHandshake(rw, our); err != nil {
109+
if err := Send(rw, handshakeMsg, our); err != nil {
110110
return nil, fmt.Errorf("protocol write error: %v", err)
111111
}
112112
rhs, err := readProtocolHandshake(rw, our)
@@ -398,10 +398,6 @@ func xor(one, other []byte) (xor []byte) {
398398
return xor
399399
}
400400

401-
func writeProtocolHandshake(w MsgWriter, our *protoHandshake) error {
402-
return EncodeMsg(w, handshakeMsg, our.Version, our.Name, our.Caps, our.ListenPort, our.ID[:])
403-
}
404-
405401
func readProtocolHandshake(r MsgReader, our *protoHandshake) (*protoHandshake, error) {
406402
// read and handle remote handshake
407403
msg, err := r.ReadMsg()

p2p/message.go

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"sync/atomic"
1212
"time"
1313

14-
"github.com/ethereum/go-ethereum/common"
1514
"github.com/ethereum/go-ethereum/rlp"
1615
)
1716

@@ -28,13 +27,7 @@ type Msg struct {
2827
Payload io.Reader
2928
}
3029

31-
// NewMsg creates an RLP-encoded message with the given code.
32-
func NewMsg(code uint64, params ...interface{}) Msg {
33-
p := bytes.NewReader(common.Encode(params))
34-
return Msg{Code: code, Size: uint32(p.Len()), Payload: p}
35-
}
36-
37-
// Decode parse the RLP content of a message into
30+
// Decode parses the RLP content of a message into
3831
// the given value, which must be a pointer.
3932
//
4033
// For the decoding rules, please see package rlp.
@@ -76,13 +69,30 @@ type MsgReadWriter interface {
7669
MsgWriter
7770
}
7871

79-
// EncodeMsg writes an RLP-encoded message with the given code and
80-
// data elements.
81-
func EncodeMsg(w MsgWriter, code uint64, data ...interface{}) error {
82-
return w.WriteMsg(NewMsg(code, data...))
72+
// Send writes an RLP-encoded message with the given code.
73+
// data should encode as an RLP list.
74+
func Send(w MsgWriter, msgcode uint64, data interface{}) error {
75+
size, r, err := rlp.EncodeToReader(data)
76+
if err != nil {
77+
return err
78+
}
79+
return w.WriteMsg(Msg{Code: msgcode, Size: uint32(size), Payload: r})
80+
}
81+
82+
// SendItems writes an RLP with the given code and data elements.
83+
// For a call such as:
84+
//
85+
// SendItems(w, code, e1, e2, e3)
86+
//
87+
// the message payload will be an RLP list containing the items:
88+
//
89+
// [e1, e2, e3]
90+
//
91+
func SendItems(w MsgWriter, msgcode uint64, elems ...interface{}) error {
92+
return Send(w, msgcode, elems)
8393
}
8494

85-
// netWrapper wrapsa MsgReadWriter with locks around
95+
// netWrapper wraps a MsgReadWriter with locks around
8696
// ReadMsg/WriteMsg and applies read/write deadlines.
8797
type netWrapper struct {
8898
rmu, wmu sync.Mutex

p2p/message_test.go

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,33 +5,17 @@ import (
55
"encoding/hex"
66
"fmt"
77
"io"
8-
"io/ioutil"
98
"runtime"
109
"strings"
1110
"testing"
1211
"time"
1312
)
1413

15-
func TestNewMsg(t *testing.T) {
16-
msg := NewMsg(3, 1, "000")
17-
if msg.Code != 3 {
18-
t.Errorf("incorrect code %d, want %d", msg.Code)
19-
}
20-
expect := unhex("c50183303030")
21-
if msg.Size != uint32(len(expect)) {
22-
t.Errorf("incorrect size %d, want %d", msg.Size, len(expect))
23-
}
24-
pl, _ := ioutil.ReadAll(msg.Payload)
25-
if !bytes.Equal(pl, expect) {
26-
t.Errorf("incorrect payload content, got %x, want %x", pl, expect)
27-
}
28-
}
29-
3014
func ExampleMsgPipe() {
3115
rw1, rw2 := MsgPipe()
3216
go func() {
33-
EncodeMsg(rw1, 8, []byte{0, 0})
34-
EncodeMsg(rw1, 5, []byte{1, 1})
17+
Send(rw1, 8, [][]byte{{0, 0}})
18+
Send(rw1, 5, [][]byte{{1, 1}})
3519
rw1.Close()
3620
}()
3721

@@ -40,7 +24,7 @@ func ExampleMsgPipe() {
4024
if err != nil {
4125
break
4226
}
43-
var data [1][]byte
27+
var data [][]byte
4428
msg.Decode(&data)
4529
fmt.Printf("msg: %d, %x\n", msg.Code, data[0])
4630
}
@@ -55,7 +39,7 @@ loop:
5539
rw1, rw2 := MsgPipe()
5640
done := make(chan struct{})
5741
go func() {
58-
if err := EncodeMsg(rw1, 1); err == nil {
42+
if err := SendItems(rw1, 1); err == nil {
5943
t.Error("EncodeMsg returned nil error")
6044
} else if err != ErrPipeClosed {
6145
t.Error("EncodeMsg returned wrong error: got %v, want %v", err, ErrPipeClosed)

p2p/peer.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ loop:
132132
select {
133133
case <-ping.C:
134134
go func() {
135-
if err := EncodeMsg(p.rw, pingMsg, nil); err != nil {
135+
if err := SendItems(p.rw, pingMsg); err != nil {
136136
p.protoErr <- err
137137
return
138138
}
@@ -161,7 +161,7 @@ loop:
161161
func (p *Peer) politeDisconnect(reason DiscReason) {
162162
done := make(chan struct{})
163163
go func() {
164-
EncodeMsg(p.rw, discMsg, uint(reason))
164+
SendItems(p.rw, discMsg, uint(reason))
165165
// Wait for the other side to close the connection.
166166
// Discard any data that they send until then.
167167
io.Copy(ioutil.Discard, p.conn)
@@ -192,7 +192,7 @@ func (p *Peer) handle(msg Msg) error {
192192
switch {
193193
case msg.Code == pingMsg:
194194
msg.Discard()
195-
go EncodeMsg(p.rw, pongMsg)
195+
go SendItems(p.rw, pongMsg)
196196
case msg.Code == discMsg:
197197
var reason [1]DiscReason
198198
// no need to discard or for error checking, we'll close the

p2p/peer_test.go

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,10 @@ import (
44
"bytes"
55
"fmt"
66
"io"
7-
"io/ioutil"
87
"net"
98
"reflect"
109
"testing"
1110
"time"
12-
13-
"github.com/ethereum/go-ethereum/rlp"
1411
)
1512

1613
var discard = Protocol{
@@ -55,13 +52,13 @@ func TestPeerProtoReadMsg(t *testing.T) {
5552
Name: "a",
5653
Length: 5,
5754
Run: func(peer *Peer, rw MsgReadWriter) error {
58-
if err := expectMsg(rw, 2, []uint{1}); err != nil {
55+
if err := ExpectMsg(rw, 2, []uint{1}); err != nil {
5956
t.Error(err)
6057
}
61-
if err := expectMsg(rw, 3, []uint{2}); err != nil {
58+
if err := ExpectMsg(rw, 3, []uint{2}); err != nil {
6259
t.Error(err)
6360
}
64-
if err := expectMsg(rw, 4, []uint{3}); err != nil {
61+
if err := ExpectMsg(rw, 4, []uint{3}); err != nil {
6562
t.Error(err)
6663
}
6764
close(done)
@@ -72,9 +69,9 @@ func TestPeerProtoReadMsg(t *testing.T) {
7269
closer, rw, _, errc := testPeer([]Protocol{proto})
7370
defer closer.Close()
7471

75-
EncodeMsg(rw, baseProtocolLength+2, 1)
76-
EncodeMsg(rw, baseProtocolLength+3, 2)
77-
EncodeMsg(rw, baseProtocolLength+4, 3)
72+
Send(rw, baseProtocolLength+2, []uint{1})
73+
Send(rw, baseProtocolLength+3, []uint{2})
74+
Send(rw, baseProtocolLength+4, []uint{3})
7875

7976
select {
8077
case <-done:
@@ -92,10 +89,10 @@ func TestPeerProtoEncodeMsg(t *testing.T) {
9289
Name: "a",
9390
Length: 2,
9491
Run: func(peer *Peer, rw MsgReadWriter) error {
95-
if err := EncodeMsg(rw, 2); err == nil {
92+
if err := SendItems(rw, 2); err == nil {
9693
t.Error("expected error for out-of-range msg code, got nil")
9794
}
98-
if err := EncodeMsg(rw, 1, "foo", "bar"); err != nil {
95+
if err := SendItems(rw, 1, "foo", "bar"); err != nil {
9996
t.Errorf("write error: %v", err)
10097
}
10198
return nil
@@ -104,7 +101,7 @@ func TestPeerProtoEncodeMsg(t *testing.T) {
104101
closer, rw, _, _ := testPeer([]Protocol{proto})
105102
defer closer.Close()
106103

107-
if err := expectMsg(rw, 17, []string{"foo", "bar"}); err != nil {
104+
if err := ExpectMsg(rw, 17, []string{"foo", "bar"}); err != nil {
108105
t.Error(err)
109106
}
110107
}
@@ -115,11 +112,15 @@ func TestPeerWriteForBroadcast(t *testing.T) {
115112
closer, rw, peer, peerErr := testPeer([]Protocol{discard})
116113
defer closer.Close()
117114

115+
emptymsg := func(code uint64) Msg {
116+
return Msg{Code: code, Size: 0, Payload: bytes.NewReader(nil)}
117+
}
118+
118119
// test write errors
119-
if err := peer.writeProtoMsg("b", NewMsg(3)); err == nil {
120+
if err := peer.writeProtoMsg("b", emptymsg(3)); err == nil {
120121
t.Errorf("expected error for unknown protocol, got nil")
121122
}
122-
if err := peer.writeProtoMsg("discard", NewMsg(8)); err == nil {
123+
if err := peer.writeProtoMsg("discard", emptymsg(8)); err == nil {
123124
t.Errorf("expected error for out-of-range msg code, got nil")
124125
} else if perr, ok := err.(*peerError); !ok || perr.Code != errInvalidMsgCode {
125126
t.Errorf("wrong error for out-of-range msg code, got %#v", err)
@@ -128,14 +129,14 @@ func TestPeerWriteForBroadcast(t *testing.T) {
128129
// setup for reading the message on the other end
129130
read := make(chan struct{})
130131
go func() {
131-
if err := expectMsg(rw, 16, nil); err != nil {
132+
if err := ExpectMsg(rw, 16, nil); err != nil {
132133
t.Error(err)
133134
}
134135
close(read)
135136
}()
136137

137138
// test successful write
138-
if err := peer.writeProtoMsg("discard", NewMsg(0)); err != nil {
139+
if err := peer.writeProtoMsg("discard", emptymsg(0)); err != nil {
139140
t.Errorf("expect no error for known protocol: %v", err)
140141
}
141142
select {
@@ -150,10 +151,10 @@ func TestPeerPing(t *testing.T) {
150151

151152
closer, rw, _, _ := testPeer(nil)
152153
defer closer.Close()
153-
if err := EncodeMsg(rw, pingMsg); err != nil {
154+
if err := SendItems(rw, pingMsg); err != nil {
154155
t.Fatal(err)
155156
}
156-
if err := expectMsg(rw, pongMsg, nil); err != nil {
157+
if err := ExpectMsg(rw, pongMsg, nil); err != nil {
157158
t.Error(err)
158159
}
159160
}
@@ -163,10 +164,10 @@ func TestPeerDisconnect(t *testing.T) {
163164

164165
closer, rw, _, disc := testPeer(nil)
165166
defer closer.Close()
166-
if err := EncodeMsg(rw, discMsg, DiscQuitting); err != nil {
167+
if err := SendItems(rw, discMsg, DiscQuitting); err != nil {
167168
t.Fatal(err)
168169
}
169-
if err := expectMsg(rw, discMsg, []interface{}{DiscRequested}); err != nil {
170+
if err := ExpectMsg(rw, discMsg, []interface{}{DiscRequested}); err != nil {
170171
t.Error(err)
171172
}
172173
closer.Close() // make test end faster

p2p/rlpx_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ ba628a4ba590cb43f7848f41c4382885
3030
`)
3131

3232
// Check WriteMsg. This puts a message into the buffer.
33-
if err := EncodeMsg(rw, 8, 1, 2, 3, 4); err != nil {
33+
if err := Send(rw, 8, []uint{1, 2, 3, 4}); err != nil {
3434
t.Fatalf("WriteMsg error: %v", err)
3535
}
3636
written := buf.Bytes()
@@ -102,7 +102,7 @@ func TestRlpxFrameRW(t *testing.T) {
102102
for i := 0; i < 10; i++ {
103103
// write message into conn buffer
104104
wmsg := []interface{}{"foo", "bar", strings.Repeat("test", i)}
105-
err := EncodeMsg(rw1, uint64(i), wmsg...)
105+
err := Send(rw1, uint64(i), wmsg)
106106
if err != nil {
107107
t.Fatalf("WriteMsg error (i=%d): %v", i, err)
108108
}

p2p/server.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ import (
99
"sync"
1010
"time"
1111

12-
"github.com/ethereum/go-ethereum/common"
1312
"github.com/ethereum/go-ethereum/logger"
1413
"github.com/ethereum/go-ethereum/p2p/discover"
1514
"github.com/ethereum/go-ethereum/p2p/nat"
15+
"github.com/ethereum/go-ethereum/rlp"
1616
)
1717

1818
const (
@@ -129,10 +129,14 @@ func (srv *Server) SuggestPeer(n *discover.Node) {
129129

130130
// Broadcast sends an RLP-encoded message to all connected peers.
131131
// This method is deprecated and will be removed later.
132-
func (srv *Server) Broadcast(protocol string, code uint64, data ...interface{}) {
132+
func (srv *Server) Broadcast(protocol string, code uint64, data interface{}) error {
133133
var payload []byte
134134
if data != nil {
135-
payload = common.Encode(data)
135+
var err error
136+
payload, err = rlp.EncodeToBytes(data)
137+
if err != nil {
138+
return err
139+
}
136140
}
137141
srv.lock.RLock()
138142
defer srv.lock.RUnlock()
@@ -146,6 +150,7 @@ func (srv *Server) Broadcast(protocol string, code uint64, data ...interface{})
146150
peer.writeProtoMsg(protocol, msg)
147151
}
148152
}
153+
return nil
149154
}
150155

151156
// Start starts running the server.

p2p/server_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ func TestServerBroadcast(t *testing.T) {
149149
connected.Wait()
150150

151151
// broadcast one message
152-
srv.Broadcast("discard", 0, "foo")
152+
srv.Broadcast("discard", 0, []string{"foo"})
153153
golden := unhex("66e94d166f0a2c3b884cfa59ca34")
154154

155155
// check that the message has been written everywhere

0 commit comments

Comments
 (0)