github.com/murrekatt/go-ethereum@v1.5.8-0.20170123175102-fc52f2c007fb/p2p/discv5/udp.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package discv5 18 19 import ( 20 "bytes" 21 "crypto/ecdsa" 22 "errors" 23 "fmt" 24 "net" 25 "time" 26 27 "github.com/ethereum/go-ethereum/common" 28 "github.com/ethereum/go-ethereum/crypto" 29 "github.com/ethereum/go-ethereum/logger" 30 "github.com/ethereum/go-ethereum/logger/glog" 31 "github.com/ethereum/go-ethereum/p2p/nat" 32 "github.com/ethereum/go-ethereum/p2p/netutil" 33 "github.com/ethereum/go-ethereum/rlp" 34 ) 35 36 const Version = 4 37 38 // Errors 39 var ( 40 errPacketTooSmall = errors.New("too small") 41 errBadHash = errors.New("bad hash") 42 errExpired = errors.New("expired") 43 errUnsolicitedReply = errors.New("unsolicited reply") 44 errUnknownNode = errors.New("unknown node") 45 errTimeout = errors.New("RPC timeout") 46 errClockWarp = errors.New("reply deadline too far in the future") 47 errClosed = errors.New("socket closed") 48 ) 49 50 // Timeouts 51 const ( 52 respTimeout = 500 * time.Millisecond 53 sendTimeout = 500 * time.Millisecond 54 expiration = 20 * time.Second 55 56 ntpFailureThreshold = 32 // Continuous timeouts after which to check NTP 57 ntpWarningCooldown = 10 * time.Minute // Minimum amount of time to pass before repeating NTP warning 58 driftThreshold = 10 * time.Second // Allowed clock drift before warning user 59 ) 60 61 // RPC request structures 62 type ( 63 ping struct { 64 Version uint 65 From, To rpcEndpoint 66 Expiration uint64 67 68 // v5 69 Topics []Topic 70 71 // Ignore additional fields (for forward compatibility). 72 Rest []rlp.RawValue `rlp:"tail"` 73 } 74 75 // pong is the reply to ping. 76 pong struct { 77 // This field should mirror the UDP envelope address 78 // of the ping packet, which provides a way to discover the 79 // the external address (after NAT). 80 To rpcEndpoint 81 82 ReplyTok []byte // This contains the hash of the ping packet. 83 Expiration uint64 // Absolute timestamp at which the packet becomes invalid. 84 85 // v5 86 TopicHash common.Hash 87 TicketSerial uint32 88 WaitPeriods []uint32 89 90 // Ignore additional fields (for forward compatibility). 91 Rest []rlp.RawValue `rlp:"tail"` 92 } 93 94 // findnode is a query for nodes close to the given target. 95 findnode struct { 96 Target NodeID // doesn't need to be an actual public key 97 Expiration uint64 98 // Ignore additional fields (for forward compatibility). 99 Rest []rlp.RawValue `rlp:"tail"` 100 } 101 102 // findnode is a query for nodes close to the given target. 103 findnodeHash struct { 104 Target common.Hash 105 Expiration uint64 106 // Ignore additional fields (for forward compatibility). 107 Rest []rlp.RawValue `rlp:"tail"` 108 } 109 110 // reply to findnode 111 neighbors struct { 112 Nodes []rpcNode 113 Expiration uint64 114 // Ignore additional fields (for forward compatibility). 115 Rest []rlp.RawValue `rlp:"tail"` 116 } 117 118 topicRegister struct { 119 Topics []Topic 120 Idx uint 121 Pong []byte 122 } 123 124 topicQuery struct { 125 Topic Topic 126 Expiration uint64 127 } 128 129 // reply to topicQuery 130 topicNodes struct { 131 Echo common.Hash 132 Nodes []rpcNode 133 } 134 135 rpcNode struct { 136 IP net.IP // len 4 for IPv4 or 16 for IPv6 137 UDP uint16 // for discovery protocol 138 TCP uint16 // for RLPx protocol 139 ID NodeID 140 } 141 142 rpcEndpoint struct { 143 IP net.IP // len 4 for IPv4 or 16 for IPv6 144 UDP uint16 // for discovery protocol 145 TCP uint16 // for RLPx protocol 146 } 147 ) 148 149 const ( 150 macSize = 256 / 8 151 sigSize = 520 / 8 152 headSize = macSize + sigSize // space of packet frame data 153 ) 154 155 // Neighbors replies are sent across multiple packets to 156 // stay below the 1280 byte limit. We compute the maximum number 157 // of entries by stuffing a packet until it grows too large. 158 var maxNeighbors = func() int { 159 p := neighbors{Expiration: ^uint64(0)} 160 maxSizeNode := rpcNode{IP: make(net.IP, 16), UDP: ^uint16(0), TCP: ^uint16(0)} 161 for n := 0; ; n++ { 162 p.Nodes = append(p.Nodes, maxSizeNode) 163 size, _, err := rlp.EncodeToReader(p) 164 if err != nil { 165 // If this ever happens, it will be caught by the unit tests. 166 panic("cannot encode: " + err.Error()) 167 } 168 if headSize+size+1 >= 1280 { 169 return n 170 } 171 } 172 }() 173 174 var maxTopicNodes = func() int { 175 p := topicNodes{} 176 maxSizeNode := rpcNode{IP: make(net.IP, 16), UDP: ^uint16(0), TCP: ^uint16(0)} 177 for n := 0; ; n++ { 178 p.Nodes = append(p.Nodes, maxSizeNode) 179 size, _, err := rlp.EncodeToReader(p) 180 if err != nil { 181 // If this ever happens, it will be caught by the unit tests. 182 panic("cannot encode: " + err.Error()) 183 } 184 if headSize+size+1 >= 1280 { 185 return n 186 } 187 } 188 }() 189 190 func makeEndpoint(addr *net.UDPAddr, tcpPort uint16) rpcEndpoint { 191 ip := addr.IP.To4() 192 if ip == nil { 193 ip = addr.IP.To16() 194 } 195 return rpcEndpoint{IP: ip, UDP: uint16(addr.Port), TCP: tcpPort} 196 } 197 198 func (e1 rpcEndpoint) equal(e2 rpcEndpoint) bool { 199 return e1.UDP == e2.UDP && e1.TCP == e2.TCP && e1.IP.Equal(e2.IP) 200 } 201 202 func nodeFromRPC(sender *net.UDPAddr, rn rpcNode) (*Node, error) { 203 if err := netutil.CheckRelayIP(sender.IP, rn.IP); err != nil { 204 return nil, err 205 } 206 n := NewNode(rn.ID, rn.IP, rn.UDP, rn.TCP) 207 err := n.validateComplete() 208 return n, err 209 } 210 211 func nodeToRPC(n *Node) rpcNode { 212 return rpcNode{ID: n.ID, IP: n.IP, UDP: n.UDP, TCP: n.TCP} 213 } 214 215 type ingressPacket struct { 216 remoteID NodeID 217 remoteAddr *net.UDPAddr 218 ev nodeEvent 219 hash []byte 220 data interface{} // one of the RPC structs 221 rawData []byte 222 } 223 224 type conn interface { 225 ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error) 226 WriteToUDP(b []byte, addr *net.UDPAddr) (n int, err error) 227 Close() error 228 LocalAddr() net.Addr 229 } 230 231 // udp implements the RPC protocol. 232 type udp struct { 233 conn conn 234 priv *ecdsa.PrivateKey 235 ourEndpoint rpcEndpoint 236 nat nat.Interface 237 net *Network 238 } 239 240 // ListenUDP returns a new table that listens for UDP packets on laddr. 241 func ListenUDP(priv *ecdsa.PrivateKey, laddr string, natm nat.Interface, nodeDBPath string, netrestrict *netutil.Netlist) (*Network, error) { 242 transport, err := listenUDP(priv, laddr) 243 if err != nil { 244 return nil, err 245 } 246 net, err := newNetwork(transport, priv.PublicKey, natm, nodeDBPath, netrestrict) 247 if err != nil { 248 return nil, err 249 } 250 transport.net = net 251 go transport.readLoop() 252 return net, nil 253 } 254 255 func listenUDP(priv *ecdsa.PrivateKey, laddr string) (*udp, error) { 256 addr, err := net.ResolveUDPAddr("udp", laddr) 257 if err != nil { 258 return nil, err 259 } 260 conn, err := net.ListenUDP("udp", addr) 261 if err != nil { 262 return nil, err 263 } 264 return &udp{conn: conn, priv: priv, ourEndpoint: makeEndpoint(addr, uint16(addr.Port))}, nil 265 } 266 267 func (t *udp) localAddr() *net.UDPAddr { 268 return t.conn.LocalAddr().(*net.UDPAddr) 269 } 270 271 func (t *udp) Close() { 272 t.conn.Close() 273 } 274 275 func (t *udp) send(remote *Node, ptype nodeEvent, data interface{}) (hash []byte) { 276 hash, _ = t.sendPacket(remote.ID, remote.addr(), byte(ptype), data) 277 return hash 278 } 279 280 func (t *udp) sendPing(remote *Node, toaddr *net.UDPAddr, topics []Topic) (hash []byte) { 281 hash, _ = t.sendPacket(remote.ID, toaddr, byte(pingPacket), ping{ 282 Version: Version, 283 From: t.ourEndpoint, 284 To: makeEndpoint(toaddr, uint16(toaddr.Port)), // TODO: maybe use known TCP port from DB 285 Expiration: uint64(time.Now().Add(expiration).Unix()), 286 Topics: topics, 287 }) 288 return hash 289 } 290 291 func (t *udp) sendFindnode(remote *Node, target NodeID) { 292 t.sendPacket(remote.ID, remote.addr(), byte(findnodePacket), findnode{ 293 Target: target, 294 Expiration: uint64(time.Now().Add(expiration).Unix()), 295 }) 296 } 297 298 func (t *udp) sendNeighbours(remote *Node, results []*Node) { 299 // Send neighbors in chunks with at most maxNeighbors per packet 300 // to stay below the 1280 byte limit. 301 p := neighbors{Expiration: uint64(time.Now().Add(expiration).Unix())} 302 for i, result := range results { 303 p.Nodes = append(p.Nodes, nodeToRPC(result)) 304 if len(p.Nodes) == maxNeighbors || i == len(results)-1 { 305 t.sendPacket(remote.ID, remote.addr(), byte(neighborsPacket), p) 306 p.Nodes = p.Nodes[:0] 307 } 308 } 309 } 310 311 func (t *udp) sendFindnodeHash(remote *Node, target common.Hash) { 312 t.sendPacket(remote.ID, remote.addr(), byte(findnodeHashPacket), findnodeHash{ 313 Target: target, 314 Expiration: uint64(time.Now().Add(expiration).Unix()), 315 }) 316 } 317 318 func (t *udp) sendTopicRegister(remote *Node, topics []Topic, idx int, pong []byte) { 319 t.sendPacket(remote.ID, remote.addr(), byte(topicRegisterPacket), topicRegister{ 320 Topics: topics, 321 Idx: uint(idx), 322 Pong: pong, 323 }) 324 } 325 326 func (t *udp) sendTopicNodes(remote *Node, queryHash common.Hash, nodes []*Node) { 327 p := topicNodes{Echo: queryHash} 328 if len(nodes) == 0 { 329 t.sendPacket(remote.ID, remote.addr(), byte(topicNodesPacket), p) 330 return 331 } 332 for i, result := range nodes { 333 if netutil.CheckRelayIP(remote.IP, result.IP) != nil { 334 continue 335 } 336 p.Nodes = append(p.Nodes, nodeToRPC(result)) 337 if len(p.Nodes) == maxTopicNodes || i == len(nodes)-1 { 338 t.sendPacket(remote.ID, remote.addr(), byte(topicNodesPacket), p) 339 p.Nodes = p.Nodes[:0] 340 } 341 } 342 } 343 344 func (t *udp) sendPacket(toid NodeID, toaddr *net.UDPAddr, ptype byte, req interface{}) (hash []byte, err error) { 345 //fmt.Println("sendPacket", nodeEvent(ptype), toaddr.String(), toid.String()) 346 packet, hash, err := encodePacket(t.priv, ptype, req) 347 if err != nil { 348 //fmt.Println(err) 349 return hash, err 350 } 351 glog.V(logger.Detail).Infof(">>> %v to %x@%v\n", nodeEvent(ptype), toid[:8], toaddr) 352 if _, err = t.conn.WriteToUDP(packet, toaddr); err != nil { 353 glog.V(logger.Detail).Infoln("UDP send failed:", err) 354 } 355 //fmt.Println(err) 356 return hash, err 357 } 358 359 // zeroed padding space for encodePacket. 360 var headSpace = make([]byte, headSize) 361 362 func encodePacket(priv *ecdsa.PrivateKey, ptype byte, req interface{}) (p, hash []byte, err error) { 363 b := new(bytes.Buffer) 364 b.Write(headSpace) 365 b.WriteByte(ptype) 366 if err := rlp.Encode(b, req); err != nil { 367 glog.V(logger.Error).Infoln("error encoding packet:", err) 368 return nil, nil, err 369 } 370 packet := b.Bytes() 371 sig, err := crypto.Sign(crypto.Keccak256(packet[headSize:]), priv) 372 if err != nil { 373 glog.V(logger.Error).Infoln("could not sign packet:", err) 374 return nil, nil, err 375 } 376 copy(packet[macSize:], sig) 377 // add the hash to the front. Note: this doesn't protect the 378 // packet in any way. 379 hash = crypto.Keccak256(packet[macSize:]) 380 copy(packet, hash) 381 return packet, hash, nil 382 } 383 384 // readLoop runs in its own goroutine. it injects ingress UDP packets 385 // into the network loop. 386 func (t *udp) readLoop() { 387 defer t.conn.Close() 388 // Discovery packets are defined to be no larger than 1280 bytes. 389 // Packets larger than this size will be cut at the end and treated 390 // as invalid because their hash won't match. 391 buf := make([]byte, 1280) 392 for { 393 nbytes, from, err := t.conn.ReadFromUDP(buf) 394 if netutil.IsTemporaryError(err) { 395 // Ignore temporary read errors. 396 glog.V(logger.Debug).Infof("Temporary read error: %v", err) 397 continue 398 } else if err != nil { 399 // Shut down the loop for permament errors. 400 glog.V(logger.Debug).Infof("Read error: %v", err) 401 return 402 } 403 t.handlePacket(from, buf[:nbytes]) 404 } 405 } 406 407 func (t *udp) handlePacket(from *net.UDPAddr, buf []byte) error { 408 pkt := ingressPacket{remoteAddr: from} 409 if err := decodePacket(buf, &pkt); err != nil { 410 glog.V(logger.Debug).Infof("Bad packet from %v: %v\n", from, err) 411 //fmt.Println("bad packet", err) 412 return err 413 } 414 t.net.reqReadPacket(pkt) 415 return nil 416 } 417 418 func decodePacket(buffer []byte, pkt *ingressPacket) error { 419 if len(buffer) < headSize+1 { 420 return errPacketTooSmall 421 } 422 buf := make([]byte, len(buffer)) 423 copy(buf, buffer) 424 hash, sig, sigdata := buf[:macSize], buf[macSize:headSize], buf[headSize:] 425 shouldhash := crypto.Keccak256(buf[macSize:]) 426 if !bytes.Equal(hash, shouldhash) { 427 return errBadHash 428 } 429 fromID, err := recoverNodeID(crypto.Keccak256(buf[headSize:]), sig) 430 if err != nil { 431 return err 432 } 433 pkt.rawData = buf 434 pkt.hash = hash 435 pkt.remoteID = fromID 436 switch pkt.ev = nodeEvent(sigdata[0]); pkt.ev { 437 case pingPacket: 438 pkt.data = new(ping) 439 case pongPacket: 440 pkt.data = new(pong) 441 case findnodePacket: 442 pkt.data = new(findnode) 443 case neighborsPacket: 444 pkt.data = new(neighbors) 445 case findnodeHashPacket: 446 pkt.data = new(findnodeHash) 447 case topicRegisterPacket: 448 pkt.data = new(topicRegister) 449 case topicQueryPacket: 450 pkt.data = new(topicQuery) 451 case topicNodesPacket: 452 pkt.data = new(topicNodes) 453 default: 454 return fmt.Errorf("unknown packet type: %d", sigdata[0]) 455 } 456 s := rlp.NewStream(bytes.NewReader(sigdata[1:]), 0) 457 err = s.Decode(pkt.data) 458 return err 459 }