github.com/annchain/OG@v0.0.9/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 "github.com/annchain/OG/arefactor/common/goroutine" 25 "github.com/annchain/OG/arefactor/og/types" 26 ogcrypto2 "github.com/annchain/OG/deprecated/ogcrypto" 27 "net" 28 "time" 29 30 "github.com/annchain/OG/p2p/nat" 31 "github.com/annchain/OG/p2p/netutil" 32 ) 33 34 //go:generate msgp 35 const Version = 4 36 37 // Errors 38 var ( 39 errPacketTooSmall = errors.New("too small") 40 errBadPrefix = errors.New("bad prefix") 41 errTimeout = errors.New("RPC timeout") 42 ) 43 44 // Timeouts 45 const ( 46 respTimeout = 500 * time.Millisecond 47 expiration = 20 * time.Second 48 49 driftThreshold = 10 * time.Second // Allowed clock drift before warning user 50 ) 51 52 // RPC request structures 53 54 type CommonHash [32]byte 55 56 type ( 57 //msgp:tuple Ping 58 Ping struct { 59 Version uint 60 From, To RpcEndpoint 61 Expiration uint64 62 63 // v5 64 //Topics []Topic 65 Topics []string 66 // Ignore additional fields (for forward compatibility). 67 Rest [][]byte `rlp:"tail"` 68 } 69 70 // pong is the reply to ping. 71 //msgp:tuple Pong 72 Pong struct { 73 // This field should mirror the UDP envelope address 74 // of the ping packet, which provides a way to discover the 75 // the external address (after NAT). 76 To RpcEndpoint 77 78 ReplyTok []byte // This contains the hash of the ping packet. 79 Expiration uint64 // Absolute timestamp at which the packet becomes invalid. 80 81 // v5 82 TopicHash CommonHash 83 TicketSerial uint32 84 WaitPeriods []uint32 85 86 // Ignore additional fields (for forward compatibility). 87 Rest [][]byte `rlp:"tail"` 88 } 89 90 // findnode is a query for nodes close to the given target. 91 //msgp:tuple Findnode 92 Findnode struct { 93 //Target NodeID // doesn't need to be an actual public key 94 Target [64]byte 95 Expiration uint64 96 // Ignore additional fields (for forward compatibility). 97 Rest [][]byte `rlp:"tail"` 98 } 99 100 // findnode is a query for nodes close to the given target. 101 //msgp:tuple FindnodeHash 102 FindnodeHash struct { 103 //Target common.Hash 104 Target CommonHash 105 Expiration uint64 106 // Ignore additional fields (for forward compatibility). 107 Rest [][]byte `rlp:"tail"` 108 } 109 110 // reply to findnode 111 //msgp:tuple Neighbors 112 Neighbors struct { 113 Nodes []RpcNode 114 Expiration uint64 115 // Ignore additional fields (for forward compatibility). 116 Rest [][]byte `rlp:"tail"` 117 } 118 //msgp:tuple TopicRegister 119 TopicRegister struct { 120 //Topics []Topic 121 Topics []string 122 Idx uint 123 Pong []byte 124 } 125 //msgp:tuple TopicQuery 126 TopicQuery struct { 127 //Topic Topic 128 Topic string 129 Expiration uint64 130 } 131 132 // reply to topicQuery 133 //msgp:tuple TopicNodes 134 TopicNodes struct { 135 //Echo common.Hash 136 Echo CommonHash 137 Nodes []RpcNode 138 } 139 //msgp:tuple RpcNode 140 RpcNode struct { 141 //IP net.IP // len 4 for IPv4 or 16 for IPv6 142 IP []byte 143 UDP uint16 // for discovery protocol 144 TCP uint16 // for RLPx protocol 145 //ID NodeID 146 ID [64]byte 147 } 148 //msgp:tuple RpcEndpoint 149 RpcEndpoint struct { 150 //IP net.IP // len 4 for IPv4 or 16 for IPv6 151 IP []byte 152 UDP uint16 // for discovery protocol 153 TCP uint16 // for RLPx protocol 154 } 155 ) 156 157 var ( 158 versionPrefix = []byte("temporary discovery v5") 159 versionPrefixSize = len(versionPrefix) 160 sigSize = 520 / 8 161 headSize = versionPrefixSize + sigSize // space of packet frame data 162 ) 163 164 // Neighbors replies are sent across multiple packets to 165 // stay below the 1280 byte limit. We compute the maximum number 166 // of entries by stuffing a packet until it grows too large. 167 var maxNeighbors = func() int { 168 p := Neighbors{Expiration: ^uint64(0)} 169 maxSizeNode := RpcNode{IP: make(net.IP, 16), UDP: ^uint16(0), TCP: ^uint16(0)} 170 for n := 0; ; n++ { 171 p.Nodes = append(p.Nodes, maxSizeNode) 172 data, err := p.MarshalMsg(nil) 173 //size, _, err := rlp.EncodeToReader(p) 174 if err != nil { 175 // If this ever happens, it will be caught by the unit tests. 176 panic("cannot encode: " + err.Error()) 177 } 178 size := len(data) 179 if headSize+size+1 >= 1280 { 180 return n 181 } 182 } 183 }() 184 185 var maxTopicNodes = func() int { 186 p := TopicNodes{} 187 maxSizeNode := RpcNode{IP: make(net.IP, 16), UDP: ^uint16(0), TCP: ^uint16(0)} 188 for n := 0; ; n++ { 189 p.Nodes = append(p.Nodes, maxSizeNode) 190 //size, _, err := rlp.EncodeToReader(p) 191 _, err := p.MarshalMsg(nil) 192 193 if err != nil { 194 // If this ever happens, it will be caught by the unit tests. 195 panic("cannot encode: " + err.Error()) 196 } 197 size := p.Msgsize() 198 if headSize+size+1 >= 1280 { 199 return n 200 } 201 } 202 }() 203 204 func makeEndpoint(addr *net.UDPAddr, tcpPort uint16) RpcEndpoint { 205 ip := addr.IP.To4() 206 if ip == nil { 207 ip = addr.IP.To16() 208 } 209 return RpcEndpoint{IP: ip, UDP: uint16(addr.Port), TCP: tcpPort} 210 } 211 212 func (e1 RpcEndpoint) equal(e2 RpcEndpoint) bool { 213 e1Ip := net.IP(e1.IP) 214 return e1.UDP == e2.UDP && e1.TCP == e2.TCP && e1Ip.Equal(e2.IP) 215 } 216 217 func nodeFromRPC(sender *net.UDPAddr, rn RpcNode) (*Node, error) { 218 if err := netutil.CheckRelayIP(sender.IP, rn.IP); err != nil { 219 return nil, err 220 } 221 n := NewNode(rn.ID, rn.IP, rn.UDP, rn.TCP) 222 err := n.validateComplete() 223 return n, err 224 } 225 226 func nodeToRPC(n *Node) RpcNode { 227 return RpcNode{ID: n.ID, IP: n.IP, UDP: n.UDP, TCP: n.TCP} 228 } 229 230 type ingressPacket struct { 231 remoteID NodeID 232 remoteAddr *net.UDPAddr 233 ev nodeEvent 234 hash []byte 235 data interface{} // one of the RPC structs 236 rawData []byte 237 } 238 239 type conn interface { 240 ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error) 241 WriteToUDP(b []byte, addr *net.UDPAddr) (n int, err error) 242 Close() error 243 LocalAddr() net.Addr 244 } 245 246 // udp implements the RPC protocol. 247 type udp struct { 248 conn conn 249 priv *ecdsa.PrivateKey 250 ourEndpoint RpcEndpoint 251 nat nat.Interface 252 net *Network 253 } 254 255 // ListenUDP returns a new table that listens for UDP packets on laddr. 256 func ListenUDP(priv *ecdsa.PrivateKey, conn conn, nodeDBPath string, netrestrict *netutil.Netlist) (*Network, error) { 257 realaddr := conn.LocalAddr().(*net.UDPAddr) 258 transport, err := listenUDP(priv, conn, realaddr) 259 if err != nil { 260 return nil, err 261 } 262 net, err := newNetwork(transport, priv.PublicKey, nodeDBPath, netrestrict) 263 if err != nil { 264 return nil, err 265 } 266 log.WithField("net", net.tab.self).Info("UDP listener up") 267 transport.net = net 268 goroutine.New(transport.readLoop) 269 return net, nil 270 } 271 272 func listenUDP(priv *ecdsa.PrivateKey, conn conn, realaddr *net.UDPAddr) (*udp, error) { 273 return &udp{conn: conn, priv: priv, ourEndpoint: makeEndpoint(realaddr, uint16(realaddr.Port))}, nil 274 } 275 276 func (t *udp) localAddr() *net.UDPAddr { 277 return t.conn.LocalAddr().(*net.UDPAddr) 278 } 279 280 func (t *udp) Close() { 281 t.conn.Close() 282 } 283 284 func (t *udp) send(remote *Node, ptype nodeEvent, data []byte) (hash []byte) { 285 hash, _ = t.sendPacket(remote.ID, remote.addr(), byte(ptype), data) 286 return hash 287 } 288 289 func (t *udp) sendPing(remote *Node, toaddr *net.UDPAddr, topics []Topic) (hash []byte) { 290 ping := Ping{ 291 Version: Version, 292 From: t.ourEndpoint, 293 To: makeEndpoint(toaddr, uint16(toaddr.Port)), // TODO: maybe use known TCP port from DB 294 Expiration: uint64(time.Now().Add(expiration).Unix()), 295 Topics: topicsToStrings(topics), 296 } 297 data, _ := ping.MarshalMsg(nil) 298 hash, _ = t.sendPacket(remote.ID, toaddr, byte(pingPacket), data) 299 return hash 300 } 301 302 func (t *udp) sendFindnode(remote *Node, target NodeID) { 303 f := Findnode{ 304 Target: target, 305 Expiration: uint64(time.Now().Add(expiration).Unix()), 306 } 307 data, _ := f.MarshalMsg(nil) 308 t.sendPacket(remote.ID, remote.addr(), byte(findnodePacket), data) 309 } 310 311 func (t *udp) sendNeighbours(remote *Node, results []*Node) { 312 // Send neighbors in chunks with at most maxNeighbors per packet 313 // to stay below the 1280 byte limit. 314 p := Neighbors{Expiration: uint64(time.Now().Add(expiration).Unix())} 315 for i, result := range results { 316 p.Nodes = append(p.Nodes, nodeToRPC(result)) 317 if len(p.Nodes) == maxNeighbors || i == len(results)-1 { 318 data, _ := p.MarshalMsg(nil) 319 t.sendPacket(remote.ID, remote.addr(), byte(neighborsPacket), data) 320 p.Nodes = p.Nodes[:0] 321 } 322 } 323 } 324 325 func (t *udp) sendFindnodeHash(remote *Node, target types.Hash) { 326 f := FindnodeHash{ 327 Target: target.Bytes, 328 Expiration: uint64(time.Now().Add(expiration).Unix()), 329 } 330 data, _ := f.MarshalMsg(nil) 331 t.sendPacket(remote.ID, remote.addr(), byte(findnodeHashPacket), data) 332 } 333 334 func (t *udp) sendTopicRegister(remote *Node, topics []Topic, idx int, pong []byte) { 335 tp := TopicRegister{ 336 Topics: topicsToStrings(topics), 337 Idx: uint(idx), 338 Pong: pong, 339 } 340 data, _ := tp.MarshalMsg(nil) 341 t.sendPacket(remote.ID, remote.addr(), byte(topicRegisterPacket), data) 342 } 343 344 func (t *udp) sendTopicNodes(remote *Node, queryHash types.Hash, nodes []*Node) { 345 p := TopicNodes{Echo: queryHash.Bytes} 346 var sent bool 347 for _, result := range nodes { 348 IP := net.IP(result.IP) 349 if IP.Equal(t.net.tab.self.IP) || netutil.CheckRelayIP(remote.IP, result.IP) == nil { 350 p.Nodes = append(p.Nodes, nodeToRPC(result)) 351 } 352 if len(p.Nodes) == maxTopicNodes { 353 data, _ := p.MarshalMsg(nil) 354 t.sendPacket(remote.ID, remote.addr(), byte(topicNodesPacket), data) 355 p.Nodes = p.Nodes[:0] 356 sent = true 357 } 358 } 359 if !sent || len(p.Nodes) > 0 { 360 data, _ := p.MarshalMsg(nil) 361 t.sendPacket(remote.ID, remote.addr(), byte(topicNodesPacket), data) 362 } 363 } 364 365 func (t *udp) sendPacket(toid NodeID, toaddr *net.UDPAddr, ptype byte, data []byte) (hash []byte, err error) { 366 //fmt.Println("sendPacket", nodeEvent(ptype), toaddr.String(), toid.String()) 367 packet, hash, err := encodePacket(t.priv, ptype, data) 368 if err != nil { 369 //fmt.Println(err) 370 return hash, err 371 } 372 log.Trace(">>> %v to %x@%v", nodeEvent(ptype), toid[:8], toaddr) 373 if _, err := t.conn.WriteToUDP(packet, toaddr); err != nil { 374 log.WithError(err).Trace("UDP send failed") 375 } else { 376 //egressTrafficMeter.Mark(int64(nbytes)) 377 } 378 //fmt.Println(err) 379 return hash, err 380 } 381 382 // zeroed padding space for encodePacket. 383 var headSpace = make([]byte, headSize) 384 385 func encodePacket(priv *ecdsa.PrivateKey, ptype byte, data []byte) (p, hash []byte, err error) { 386 b := new(bytes.Buffer) 387 b.Write(headSpace) 388 b.WriteByte(ptype) 389 b.Write(data) 390 packet := b.Bytes() 391 sig, err := ogcrypto2.Sign(ogcrypto2.Keccak256(packet[headSize:]), priv) 392 if err != nil { 393 log.WithError(err).Error("could not sign packet") 394 return nil, nil, err 395 } 396 copy(packet, versionPrefix) 397 copy(packet[versionPrefixSize:], sig) 398 hash = ogcrypto2.Keccak256(packet[versionPrefixSize:]) 399 return packet, hash, nil 400 } 401 402 // readLoop runs in its own goroutine. it injects ingress UDP packets 403 // into the network loop. 404 func (t *udp) readLoop() { 405 defer t.conn.Close() 406 // Discovery packets are defined to be no larger than 1280 bytes. 407 // Packets larger than this size will be cut at the end and treated 408 // as invalid because their hash won't match. 409 buf := make([]byte, 1280) 410 for { 411 nbytes, from, err := t.conn.ReadFromUDP(buf) 412 //ingressTrafficMeter.Mark(int64(nbytes)) 413 if netutil.IsTemporaryError(err) { 414 // Ignore temporary read errors. 415 log.WithError(err).Debug("Temporary read error") 416 continue 417 } else if err != nil { 418 // Shut down the loop for permament errors. 419 log.WithError(err).Debug("Read error") 420 return 421 } 422 t.handlePacket(from, buf[:nbytes]) 423 } 424 } 425 426 func (t *udp) handlePacket(from *net.UDPAddr, buf []byte) error { 427 pkt := ingressPacket{remoteAddr: from} 428 if err := decodePacket(buf, &pkt); err != nil { 429 log.WithError(err).WithField("from", from).Debug("Bad packet") 430 //fmt.Println("bad packet", err) 431 return err 432 } 433 t.net.reqReadPacket(pkt) 434 return nil 435 } 436 437 func decodePacket(buffer []byte, pkt *ingressPacket) error { 438 if len(buffer) < headSize+1 { 439 return errPacketTooSmall 440 } 441 buf := make([]byte, len(buffer)) 442 copy(buf, buffer) 443 prefix, sig, sigdata := buf[:versionPrefixSize], buf[versionPrefixSize:headSize], buf[headSize:] 444 if !bytes.Equal(prefix, versionPrefix) { 445 return errBadPrefix 446 } 447 fromID, err := recoverNodeID(ogcrypto2.Keccak256(buf[headSize:]), sig) 448 if err != nil { 449 return err 450 } 451 pkt.rawData = buf 452 pkt.hash = ogcrypto2.Keccak256(buf[versionPrefixSize:]) 453 pkt.remoteID = fromID 454 data := sigdata[1:] 455 switch pkt.ev = nodeEvent(sigdata[0]); pkt.ev { 456 case pingPacket: 457 req := new(Ping) 458 _, err = req.UnmarshalMsg(data) 459 pkt.data = req 460 case pongPacket: 461 req := new(Pong) 462 _, err = req.UnmarshalMsg(data) 463 pkt.data = req 464 case findnodePacket: 465 req := new(Findnode) 466 _, err = req.UnmarshalMsg(data) 467 pkt.data = req 468 case neighborsPacket: 469 req := new(Neighbors) 470 _, err = req.UnmarshalMsg(data) 471 pkt.data = req 472 case findnodeHashPacket: 473 req := new(FindnodeHash) 474 _, err = req.UnmarshalMsg(data) 475 pkt.data = req 476 case topicRegisterPacket: 477 req := new(TopicRegister) 478 _, err = req.UnmarshalMsg(data) 479 pkt.data = req 480 case topicQueryPacket: 481 req := new(TopicQuery) 482 _, err = req.UnmarshalMsg(data) 483 pkt.data = req 484 case topicNodesPacket: 485 req := new(TopicNodes) 486 _, err = req.UnmarshalMsg(data) 487 pkt.data = req 488 default: 489 return fmt.Errorf("unknown packet type: %d", sigdata[0]) 490 } 491 //s := rlp.NewStream(bytes.NewReader(sigdata[1:]), 0) 492 //err = s.Decode(pkt.data) 493 return err 494 }