@@ -49,16 +49,20 @@ const (
49
49
// RPC request structures
50
50
type (
51
51
ping struct {
52
- Version uint // must match Version
53
- IP string // our IP
54
- Port uint16 // our port
52
+ Version uint
53
+ From , To rpcEndpoint
55
54
Expiration uint64
56
55
}
57
56
58
- // reply to Ping
57
+ // pong is the reply to ping.
59
58
pong struct {
60
- ReplyTok []byte
61
- Expiration uint64
59
+ // This field should mirror the UDP envelope address
60
+ // of the ping packet, which provides a way to discover the
61
+ // the external address (after NAT).
62
+ To rpcEndpoint
63
+
64
+ ReplyTok []byte // This contains the hash of the ping packet.
65
+ Expiration uint64 // Absolute timestamp at which the packet becomes invalid.
62
66
}
63
67
64
68
findnode struct {
@@ -73,12 +77,25 @@ type (
73
77
Nodes []* Node
74
78
Expiration uint64
75
79
}
80
+
81
+ rpcEndpoint struct {
82
+ IP net.IP // len 4 for IPv4 or 16 for IPv6
83
+ UDP uint16 // for discovery protocol
84
+ TCP uint16 // for RLPx protocol
85
+ }
76
86
)
77
87
78
- type rpcNode struct {
79
- IP string
80
- Port uint16
81
- ID NodeID
88
+ func makeEndpoint (addr * net.UDPAddr , tcpPort uint16 ) rpcEndpoint {
89
+ ip := addr .IP .To4 ()
90
+ if ip == nil {
91
+ ip = addr .IP .To16 ()
92
+ }
93
+ return rpcEndpoint {IP : ip , UDP : uint16 (addr .Port ), TCP : tcpPort }
94
+ }
95
+
96
+ func validNode (n * Node ) bool {
97
+ // TODO: don't accept localhost, LAN addresses from internet hosts
98
+ return ! n .IP .IsMulticast () && ! n .IP .IsUnspecified () && n .UDP != 0
82
99
}
83
100
84
101
type packet interface {
@@ -94,8 +111,9 @@ type conn interface {
94
111
95
112
// udp implements the RPC protocol.
96
113
type udp struct {
97
- conn conn
98
- priv * ecdsa.PrivateKey
114
+ conn conn
115
+ priv * ecdsa.PrivateKey
116
+ ourEndpoint rpcEndpoint
99
117
100
118
addpending chan * pending
101
119
gotreply chan reply
@@ -176,6 +194,8 @@ func newUDP(priv *ecdsa.PrivateKey, c conn, natm nat.Interface, nodeDBPath strin
176
194
realaddr = & net.UDPAddr {IP : ext , Port : realaddr .Port }
177
195
}
178
196
}
197
+ // TODO: separate TCP port
198
+ udp .ourEndpoint = makeEndpoint (realaddr , uint16 (realaddr .Port ))
179
199
udp .Table = newTable (udp , PubkeyID (& priv .PublicKey ), realaddr , nodeDBPath )
180
200
go udp .loop ()
181
201
go udp .readLoop ()
@@ -194,8 +214,8 @@ func (t *udp) ping(toid NodeID, toaddr *net.UDPAddr) error {
194
214
errc := t .pending (toid , pongPacket , func (interface {}) bool { return true })
195
215
t .send (toaddr , pingPacket , ping {
196
216
Version : Version ,
197
- IP : t . self . IP . String () ,
198
- Port : uint16 ( t . self . TCPPort ),
217
+ From : t . ourEndpoint ,
218
+ To : makeEndpoint ( toaddr , 0 ), // TODO: maybe use known TCP port from DB
199
219
Expiration : uint64 (time .Now ().Add (expiration ).Unix ()),
200
220
})
201
221
return <- errc
@@ -214,7 +234,7 @@ func (t *udp) findnode(toid NodeID, toaddr *net.UDPAddr, target NodeID) ([]*Node
214
234
reply := r .(* neighbors )
215
235
for _ , n := range reply .Nodes {
216
236
nreceived ++
217
- if n . isValid ( ) {
237
+ if validNode ( n ) {
218
238
nodes = append (nodes , n )
219
239
}
220
240
}
@@ -374,17 +394,22 @@ func (t *udp) readLoop() {
374
394
if err != nil {
375
395
return
376
396
}
377
- packet , fromID , hash , err := decodePacket (buf [:nbytes ])
378
- if err != nil {
379
- glog .V (logger .Debug ).Infof ("Bad packet from %v: %v\n " , from , err )
380
- continue
381
- }
382
- status := "ok"
383
- if err := packet .handle (t , from , fromID , hash ); err != nil {
384
- status = err .Error ()
385
- }
386
- glog .V (logger .Detail ).Infof ("<<< %v %T: %s\n " , from , packet , status )
397
+ t .handlePacket (from , buf [:nbytes ])
398
+ }
399
+ }
400
+
401
+ func (t * udp ) handlePacket (from * net.UDPAddr , buf []byte ) error {
402
+ packet , fromID , hash , err := decodePacket (buf )
403
+ if err != nil {
404
+ glog .V (logger .Debug ).Infof ("Bad packet from %v: %v\n " , from , err )
405
+ return err
387
406
}
407
+ status := "ok"
408
+ if err = packet .handle (t , from , fromID , hash ); err != nil {
409
+ status = err .Error ()
410
+ }
411
+ glog .V (logger .Detail ).Infof ("<<< %v %T: %s\n " , from , packet , status )
412
+ return err
388
413
}
389
414
390
415
func decodePacket (buf []byte ) (packet , NodeID , []byte , error ) {
@@ -425,12 +450,13 @@ func (req *ping) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) er
425
450
return errBadVersion
426
451
}
427
452
t .send (from , pongPacket , pong {
453
+ To : makeEndpoint (from , req .From .TCP ),
428
454
ReplyTok : mac ,
429
455
Expiration : uint64 (time .Now ().Add (expiration ).Unix ()),
430
456
})
431
457
if ! t .handleReply (fromID , pingPacket , req ) {
432
458
// Note: we're ignoring the provided IP address right now
433
- go t .bond (true , fromID , from , req .Port )
459
+ go t .bond (true , fromID , from , req .From . TCP )
434
460
}
435
461
return nil
436
462
}
0 commit comments