github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/p2pserver/discover/udp.go (about)

     1  package discover
     2  
     3  import (
     4  	"bytes"
     5  	"container/list"
     6  	"crypto/ecdsa"
     7  	"errors"
     8  	"fmt"
     9  	"net"
    10  	"time"
    11  
    12  	"github.com/ethereum/go-ethereum/crypto"
    13  	// "github.com/ethereum/go-ethereum/log"
    14  	"github.com/ethereum/go-ethereum/p2p/nat"
    15  	"github.com/ethereum/go-ethereum/p2p/netutil"
    16  	comm "github.com/sixexorg/magnetic-ring/common"
    17  	"github.com/sixexorg/magnetic-ring/log"
    18  	"github.com/sixexorg/magnetic-ring/rlp"
    19  )
    20  
    21  const Version = 4
    22  
    23  // Errors
    24  var (
    25  	errPacketTooSmall   = errors.New("too small")
    26  	errBadHash          = errors.New("bad hash")
    27  	errExpired          = errors.New("expired")
    28  	errUnsolicitedReply = errors.New("unsolicited reply")
    29  	errUnknownNode      = errors.New("unknown node")
    30  	errTimeout          = errors.New("RPC timeout")
    31  	errClockWarp        = errors.New("reply deadline too far in the future")
    32  	errClosed           = errors.New("socket closed")
    33  )
    34  
    35  // Timeouts
    36  const (
    37  	respTimeout = 500 * time.Millisecond
    38  	sendTimeout = 500 * time.Millisecond
    39  	expiration  = 20 * time.Second
    40  
    41  	ntpFailureThreshold = 32               // Continuous timeouts after which to check NTP
    42  	ntpWarningCooldown  = 10 * time.Minute // Minimum amount of time to pass before repeating NTP warning
    43  	driftThreshold      = 10 * time.Second // Allowed clock drift before warning user
    44  )
    45  
    46  // RPC packet types
    47  const (
    48  	pingPacket = iota + 1 // zero is 'reserved'
    49  	pongPacket
    50  	findnodePacket
    51  	neighborsPacket
    52  	findcirclePacket
    53  	neighborscirclePacket
    54  	sendcirclePacket
    55  	rtncirclePacket
    56  	sendConnectPacket
    57  	rtnconnectPacket
    58  	reqPeerOrgPacket
    59  	rntPeerOrgPacket
    60  	reqPeerConnectPacket
    61  	rntPeerConnectPacket
    62  	// circu
    63  	connectCircuOrgPacket
    64  	rtnCircuOrgPacket
    65  )
    66  
    67  // RPC request structures
    68  type (
    69  	ping struct {
    70  		Version    uint
    71  		From, To   rpcEndpoint
    72  		Expiration uint64
    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  
    86  	// findnode is a query for nodes close to the given target.
    87  	findnode struct {
    88  		Target     NodeID // doesn't need to be an actual public key
    89  		Expiration uint64
    90  	}
    91  
    92  	// reply to findnode
    93  	neighbors struct {
    94  		Nodes      []rpcNode
    95  		Count      uint64
    96  		Expiration uint64
    97  	}
    98  
    99  	rpcNode struct {
   100  		IP  net.IP // len 4 for IPv4 or 16 for IPv6
   101  		UDP uint16 // for discovery protocol
   102  		TCP uint16 // for RLPx protocol
   103  		ID  NodeID
   104  	}
   105  
   106  	rpcEndpoint struct {
   107  		IP  net.IP // len 4 for IPv4 or 16 for IPv6
   108  		UDP uint16 // for discovery protocol
   109  		TCP uint16 // for RLPx protocol
   110  	}
   111  )
   112  
   113  func makeEndpoint(addr *net.UDPAddr, tcpPort uint16) rpcEndpoint {
   114  	ip := addr.IP.To4()
   115  	if ip == nil {
   116  		ip = addr.IP.To16()
   117  	}
   118  	return rpcEndpoint{IP: ip, UDP: uint16(addr.Port), TCP: tcpPort}
   119  }
   120  
   121  func (t *udp) nodeFromRPC(sender *net.UDPAddr, rn rpcNode) (*Node, error) {
   122  	if rn.UDP <= 1024 {
   123  		return nil, errors.New("low port")
   124  	}
   125  	if err := netutil.CheckRelayIP(sender.IP, rn.IP); err != nil {
   126  		return nil, err
   127  	}
   128  	if t.netrestrict != nil && !t.netrestrict.Contains(rn.IP) {
   129  		return nil, errors.New("not contained in netrestrict whitelist")
   130  	}
   131  	n := NewNode(rn.ID, rn.IP, rn.UDP, rn.TCP)
   132  	err := n.validateComplete()
   133  	return n, err
   134  }
   135  
   136  func (t *udp) nodeFromRPC2(sender *net.UDPAddr, rn rpcNode) (*Node, error) {
   137  	if rn.UDP <= 1024 {
   138  		return nil, errors.New("low port")
   139  	}
   140  	if t.netrestrict != nil && !t.netrestrict.Contains(rn.IP) {
   141  		return nil, errors.New("not contained in netrestrict whitelist")
   142  	}
   143  	n := NewNode(rn.ID, rn.IP, rn.UDP, rn.TCP)
   144  	err := n.validateComplete()
   145  	return n, err
   146  }
   147  
   148  func nodeToRPC(n *Node) rpcNode {
   149  	return rpcNode{ID: n.ID, IP: n.IP, UDP: n.UDP, TCP: n.TCP}
   150  }
   151  
   152  type packet interface {
   153  	handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) error
   154  	name() string
   155  }
   156  
   157  type conn interface {
   158  	ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error)
   159  	WriteToUDP(b []byte, addr *net.UDPAddr) (n int, err error)
   160  	Close() error
   161  	LocalAddr() net.Addr
   162  }
   163  
   164  // table call connect info callback
   165  type callPeerConnectInfoFn func() (uint64, []uint64)
   166  
   167  // table org callback
   168  type callPeerOrgInfoFn func() (uint64, []comm.Address)
   169  
   170  // table send org connect callback
   171  type callSendConnectOrgFn func(destnode *Node, orgid comm.Address)
   172  
   173  // udp implements the RPC protocol.
   174  type udp struct {
   175  	conn        conn
   176  	netrestrict *netutil.Netlist
   177  	priv        *ecdsa.PrivateKey
   178  	ourEndpoint rpcEndpoint
   179  
   180  	addpending chan *pending
   181  	gotreply   chan reply
   182  
   183  	closing chan struct{}
   184  	nat     nat.Interface
   185  
   186  	// nomal peer callback
   187  	callPeerConnectInfo callPeerConnectInfoFn
   188  	callPeerOrgInfo     callPeerOrgInfoFn
   189  	callSendConnectOrg  callSendConnectOrgFn
   190  
   191  	*Table
   192  	// StellarNode
   193  	stellarNodeID comm.Address
   194  }
   195  
   196  // pending represents a pending reply.
   197  //
   198  // some implementations of the protocol wish to send more than one
   199  // reply packet to findnode. in general, any neighbors packet cannot
   200  // be matched up with a specific findnode packet.
   201  //
   202  // our implementation handles this by storing a callback function for
   203  // each pending reply. incoming packets from a node are dispatched
   204  // to all the callback functions for that node.
   205  type pending struct {
   206  	// these fields must match in the reply.
   207  	from  NodeID
   208  	ptype byte
   209  
   210  	// time when the request must complete
   211  	deadline time.Time
   212  
   213  	// callback is called when a matching reply arrives. if it returns
   214  	// true, the callback is removed from the pending reply queue.
   215  	// if it returns false, the reply is considered incomplete and
   216  	// the callback will be invoked again for the next matching reply.
   217  	callback func(resp interface{}) (done bool)
   218  
   219  	// errc receives nil when the callback indicates completion or an
   220  	// error if no further reply is received within the timeout.
   221  	errc chan<- error
   222  }
   223  
   224  type reply struct {
   225  	from  NodeID
   226  	ptype byte
   227  	data  interface{}
   228  	// loop indicates whether there was
   229  	// a matching request by sending on this channel.
   230  	matched chan<- bool
   231  }
   232  
   233  // ListenUDP returns a new table that listens for UDP packets on laddr.
   234  func ListenUDP(priv *ecdsa.PrivateKey, laddr string, natm nat.Interface,
   235  	nodeDBPath string, netrestrict *netutil.Netlist,
   236  	callPeerConnectInfo callPeerConnectInfoFn, callPeerOrgInfo callPeerOrgInfoFn,
   237  	callSendConnectOrg callSendConnectOrgFn, bbootnode bool,
   238  	stellarNodeID comm.Address) (*Table, error) {
   239  
   240  	addr, err := net.ResolveUDPAddr("udp", laddr)
   241  	if err != nil {
   242  		return nil, err
   243  	}
   244  	conn, err := net.ListenUDP("udp", addr)
   245  	if err != nil {
   246  		return nil, err
   247  	}
   248  	tab, _, err := newUDP(priv, conn, natm, nodeDBPath, netrestrict, callPeerConnectInfo, callPeerOrgInfo, callSendConnectOrg, bbootnode, stellarNodeID)
   249  	if err != nil {
   250  		return nil, err
   251  	}
   252  	log.Info("UDP listener up", "self", tab.self)
   253  	return tab, nil
   254  }
   255  
   256  func newUDP(priv *ecdsa.PrivateKey, c conn, natm nat.Interface, nodeDBPath string, netrestrict *netutil.Netlist,
   257  	callPeerConnectInfo callPeerConnectInfoFn, callPeerOrgInfo callPeerOrgInfoFn,
   258  	callSendConnectOrg callSendConnectOrgFn, bbootnode bool, stellarNodeID comm.Address) (*Table, *udp, error) {
   259  	udp := &udp{
   260  		conn:                c,
   261  		priv:                priv,
   262  		netrestrict:         netrestrict,
   263  		closing:             make(chan struct{}),
   264  		gotreply:            make(chan reply),
   265  		addpending:          make(chan *pending),
   266  		callPeerConnectInfo: callPeerConnectInfo,
   267  		callPeerOrgInfo:     callPeerOrgInfo,
   268  		callSendConnectOrg:  callSendConnectOrg,
   269  		stellarNodeID:       stellarNodeID,
   270  	}
   271  	udp.initUdpVariable() // init the Variable
   272  	realaddr := c.LocalAddr().(*net.UDPAddr)
   273  	if natm != nil {
   274  		if !realaddr.IP.IsLoopback() {
   275  			go nat.Map(natm, udp.closing, "udp", realaddr.Port, realaddr.Port, "ethereum discovery")
   276  		}
   277  		// TODO: react to external IP changes over time.
   278  		if ext, err := natm.ExternalIP(); err == nil {
   279  			realaddr = &net.UDPAddr{IP: ext, Port: realaddr.Port}
   280  		}
   281  	}
   282  	// TODO: separate TCP port
   283  	udp.ourEndpoint = makeEndpoint(realaddr, uint16(realaddr.Port))
   284  	fmt.Println(" ****** udp.ourEndpoint:", udp.ourEndpoint)
   285  	tab, err := newTable(udp, PubkeyID(&priv.PublicKey), realaddr, nodeDBPath, bbootnode)
   286  	if err != nil {
   287  		return nil, nil, err
   288  	}
   289  	udp.Table = tab
   290  
   291  	go udp.loop()
   292  	go udp.readLoop()
   293  	return udp.Table, udp, nil
   294  }
   295  
   296  func (t *udp) close() {
   297  	close(t.closing)
   298  	t.conn.Close()
   299  	// TODO: wait for the loops to end.
   300  }
   301  
   302  // ping sends a ping message to the given node and waits for a reply.
   303  func (t *udp) ping(toid NodeID, toaddr *net.UDPAddr) error {
   304  	// TODO: maybe check for ReplyTo field in callback to measure RTT
   305  	errc := t.pending(toid, pongPacket, func(interface{}) bool { return true })
   306  	t.send(toaddr, pingPacket, &ping{
   307  		Version:    Version,
   308  		From:       t.ourEndpoint,
   309  		To:         makeEndpoint(toaddr, 0), // TODO: maybe use known TCP port from DB
   310  		Expiration: uint64(time.Now().Add(expiration).Unix()),
   311  	})
   312  	return <-errc
   313  }
   314  
   315  func (t *udp) waitping(from NodeID) error {
   316  	return <-t.pending(from, pingPacket, func(interface{}) bool { return true })
   317  }
   318  
   319  // findnode sends a findnode request to the given node and waits until
   320  // the node has sent up to k neighbors.
   321  func (t *udp) findnode(toid NodeID, toaddr *net.UDPAddr, target NodeID) ([]*Node, error) {
   322  	nodes := make([]*Node, 0, bucketSize)
   323  	nreceived := uint64(0)
   324  	errc := t.pending(toid, neighborsPacket, func(r interface{}) bool {
   325  		reply := r.(*neighbors)
   326  		for _, rn := range reply.Nodes {
   327  			nreceived++
   328  			n, err := t.nodeFromRPC(toaddr, rn)
   329  			if err != nil {
   330  				log.Trace("Invalid neighbor node received", "ip", rn.IP, "addr", toaddr, "err", err)
   331  				continue
   332  			}
   333  			nodes = append(nodes, n)
   334  		}
   335  		// return nreceived >= bucketSize
   336  		return nreceived >= reply.Count
   337  	})
   338  	t.send(toaddr, findnodePacket, &findnode{
   339  		Target:     target,
   340  		Expiration: uint64(time.Now().Add(expiration).Unix()),
   341  	})
   342  	err := <-errc
   343  	return nodes, err
   344  }
   345  
   346  // pending adds a reply callback to the pending reply queue.
   347  // see the documentation of type pending for a detailed explanation.
   348  func (t *udp) pending(id NodeID, ptype byte, callback func(interface{}) bool) <-chan error {
   349  	ch := make(chan error, 1)
   350  	p := &pending{from: id, ptype: ptype, callback: callback, errc: ch}
   351  	select {
   352  	case t.addpending <- p:
   353  		// loop will handle it
   354  	case <-t.closing:
   355  		ch <- errClosed
   356  	}
   357  	return ch
   358  }
   359  
   360  func (t *udp) handleReply(from NodeID, ptype byte, req packet) bool {
   361  	matched := make(chan bool, 1)
   362  	select {
   363  	case t.gotreply <- reply{from, ptype, req, matched}:
   364  		// loop will handle it
   365  		return <-matched
   366  	case <-t.closing:
   367  		return false
   368  	}
   369  }
   370  
   371  // loop runs in its own goroutine. it keeps track of
   372  // the refresh timer and the pending reply queue.
   373  func (t *udp) loop() {
   374  	var (
   375  		plist        = list.New()
   376  		timeout      = time.NewTimer(0)
   377  		nextTimeout  *pending // head of plist when timeout was last reset
   378  		contTimeouts = 0      // number of continuous timeouts to do NTP checks
   379  		ntpWarnTime  = time.Unix(0, 0)
   380  	)
   381  	<-timeout.C // ignore first timeout
   382  	defer timeout.Stop()
   383  
   384  	resetTimeout := func() {
   385  		if plist.Front() == nil || nextTimeout == plist.Front().Value {
   386  			return
   387  		}
   388  		// Start the timer so it fires when the next pending reply has expired.
   389  		now := time.Now()
   390  		for el := plist.Front(); el != nil; el = el.Next() {
   391  			nextTimeout = el.Value.(*pending)
   392  			if dist := nextTimeout.deadline.Sub(now); dist < 2*respTimeout {
   393  				timeout.Reset(dist)
   394  				return
   395  			}
   396  			// Remove pending replies whose deadline is too far in the
   397  			// future. These can occur if the system clock jumped
   398  			// backwards after the deadline was assigned.
   399  			nextTimeout.errc <- errClockWarp
   400  			plist.Remove(el)
   401  		}
   402  		nextTimeout = nil
   403  		timeout.Stop()
   404  	}
   405  
   406  	for {
   407  		resetTimeout()
   408  
   409  		select {
   410  		case <-t.closing:
   411  			for el := plist.Front(); el != nil; el = el.Next() {
   412  				el.Value.(*pending).errc <- errClosed
   413  			}
   414  			return
   415  
   416  		case p := <-t.addpending:
   417  			p.deadline = time.Now().Add(respTimeout)
   418  			plist.PushBack(p)
   419  
   420  		case r := <-t.gotreply:
   421  			var matched bool
   422  			for el := plist.Front(); el != nil; el = el.Next() {
   423  				p := el.Value.(*pending)
   424  				if p.from == r.from && p.ptype == r.ptype {
   425  					matched = true
   426  					// Remove the matcher if its callback indicates
   427  					// that all replies have been received. This is
   428  					// required for packet types that expect multiple
   429  					// reply packets.
   430  					if p.callback(r.data) {
   431  						p.errc <- nil
   432  						plist.Remove(el)
   433  					}
   434  					// Reset the continuous timeout counter (time drift detection)
   435  					contTimeouts = 0
   436  				}
   437  			}
   438  			r.matched <- matched
   439  
   440  		case now := <-timeout.C:
   441  			nextTimeout = nil
   442  
   443  			// Notify and remove callbacks whose deadline is in the past.
   444  			for el := plist.Front(); el != nil; el = el.Next() {
   445  				p := el.Value.(*pending)
   446  				if now.After(p.deadline) || now.Equal(p.deadline) {
   447  					fmt.Println("======>>>>>>>>>udp loop", "from", p.from.String(), "type", p.ptype, "errTimeout", errTimeout)
   448  					p.errc <- errTimeout
   449  					plist.Remove(el)
   450  					contTimeouts++
   451  				}
   452  			}
   453  			// If we've accumulated too many timeouts, do an NTP time sync check
   454  			if contTimeouts > ntpFailureThreshold {
   455  				if time.Since(ntpWarnTime) >= ntpWarningCooldown {
   456  					ntpWarnTime = time.Now()
   457  					go checkClockDrift()
   458  				}
   459  				contTimeouts = 0
   460  			}
   461  		}
   462  	}
   463  }
   464  
   465  const (
   466  	macSize  = 256 / 8
   467  	sigSize  = 520 / 8
   468  	headSize = macSize + sigSize // space of packet frame data
   469  )
   470  
   471  var (
   472  	headSpace = make([]byte, headSize)
   473  
   474  	// Neighbors replies are sent across multiple packets to
   475  	// stay below the 1280 byte limit. We compute the maximum number
   476  	// of entries by stuffing a packet until it grows too large.
   477  	maxNeighbors   int
   478  	maxPeerOrg     int
   479  	maxPeerConnect int
   480  )
   481  
   482  func (t *udp) initUdpVariable() {
   483  	p := neighbors{Expiration: ^uint64(0)}
   484  	maxSizeNode := rpcNode{IP: make(net.IP, 16), UDP: ^uint16(0), TCP: ^uint16(0)}
   485  	for n := 0; ; n++ {
   486  		p.Nodes = append(p.Nodes, maxSizeNode)
   487  		size, _, err := rlp.EncodeToReader(p)
   488  		if err != nil {
   489  			// If this ever happens, it will be caught by the unit tests.
   490  			panic("cannot encode: " + err.Error())
   491  		}
   492  		if headSize+size+1 >= 1280 {
   493  			maxNeighbors = n
   494  			break
   495  		}
   496  	}
   497  	fmt.Println(" ******* maxNeighbors:", maxNeighbors)
   498  	calcMaxPeerOrg()
   499  	calcMaxPeerConnect()
   500  
   501  }
   502  
   503  func calcMaxPeerOrg() {
   504  	add, err := comm.ToAddress("ct0bbbbabbbbabbbbabbbbabbbbabbbbabb")
   505  	if err == nil {
   506  		fmt.Println(" ******* P2PServer testOrg add:", add)
   507  	} else {
   508  		return
   509  	}
   510  
   511  	p := rntPeerOrg{
   512  		Expiration: ^uint64(0),
   513  		Num:        100,
   514  		OwnID:      uint64(100),
   515  	}
   516  	p.Orgs = make([]comm.Address, 0)
   517  	// maxSizeNode := peerOrgInfo{OwnID: uint64(100), OrgID: add }
   518  	for n := 0; ; n++ {
   519  		p.Orgs = append(p.Orgs, add)
   520  		size, _, err := rlp.EncodeToReader(p)
   521  		if err != nil {
   522  			// If this ever happens, it will be caught by the unit tests.
   523  			panic("cannot encode: " + err.Error())
   524  		}
   525  		if headSize+size+1 >= 1280 {
   526  			maxPeerOrg = n
   527  			break
   528  		}
   529  	}
   530  	fmt.Println(" ******* maxPeerOrg:", maxPeerOrg)
   531  }
   532  
   533  func calcMaxPeerConnect() {
   534  	p := rntPeerConnect{Expiration: ^uint64(0)}
   535  	// maxSizeNode := peerOrgInfo{RemoteID: uint64(100), OrgID: add }
   536  	for n := 0; ; n++ {
   537  		p.RemoteID = append(p.RemoteID, uint64(100))
   538  		size, _, err := rlp.EncodeToReader(p)
   539  		if err != nil {
   540  			// If this ever happens, it will be caught by the unit tests.
   541  			panic("cannot encode: " + err.Error())
   542  		}
   543  		if headSize+size+1 >= 1280 {
   544  			maxPeerConnect = n
   545  			break
   546  		}
   547  	}
   548  	fmt.Println(" ******* maxPeerConnect:", maxPeerConnect)
   549  }
   550  
   551  func (t *udp) send(toaddr *net.UDPAddr, ptype byte, req packet) error {
   552  	packet, err := encodePacket(t.priv, ptype, req)
   553  	if err != nil {
   554  		return err
   555  	}
   556  	_, err = t.conn.WriteToUDP(packet, toaddr)
   557  	if err != nil {
   558  		fmt.Println("---udp send", toaddr.IP.String(), toaddr.Port, err)
   559  		log.Info("udpsenddebug", "ip:",toaddr.IP.String(), "port:",toaddr.Port, "err:",err)
   560  	}
   561  	log.Trace(">> "+req.name(), "addr", toaddr, "err", err)
   562  	return err
   563  }
   564  
   565  func encodePacket(priv *ecdsa.PrivateKey, ptype byte, req interface{}) ([]byte, error) {
   566  	b := new(bytes.Buffer)
   567  	b.Write(headSpace)
   568  	b.WriteByte(ptype)
   569  	if err := rlp.Encode(b, req); err != nil {
   570  		log.Error("Can't encode discv4 packet", "err", err)
   571  		return nil, err
   572  	}
   573  	packet := b.Bytes()
   574  	sig, err := crypto.Sign(crypto.Keccak256(packet[headSize:]), priv)
   575  	if err != nil {
   576  		log.Error("Can't sign discv4 packet", "err", err)
   577  		return nil, err
   578  	}
   579  	copy(packet[macSize:], sig)
   580  	// add the hash to the front. Note: this doesn't protect the
   581  	// packet in any way. Our public key will be part of this hash in
   582  	// The future.
   583  	copy(packet, crypto.Keccak256(packet[macSize:]))
   584  	return packet, nil
   585  }
   586  
   587  // readLoop runs in its own goroutine. it handles incoming UDP packets.
   588  func (t *udp) readLoop() {
   589  	defer t.conn.Close()
   590  	// Discovery packets are defined to be no larger than 1280 bytes.
   591  	// Packets larger than this size will be cut at the end and treated
   592  	// as invalid because their hash won't match.
   593  	buf := make([]byte, 1280)
   594  	for {
   595  		nbytes, from, err := t.conn.ReadFromUDP(buf)
   596  		if netutil.IsTemporaryError(err) {
   597  			// Ignore temporary read errors.
   598  			log.Debug("Temporary UDP read error", "err", err)
   599  			continue
   600  		} else if err != nil {
   601  			// Shut down the loop for permament errors.
   602  			log.Debug("UDP read error", "err", err)
   603  			return
   604  		}
   605  		t.handlePacket(from, buf[:nbytes])
   606  	}
   607  }
   608  
   609  func (t *udp) handlePacket(from *net.UDPAddr, buf []byte) error {
   610  	packet, fromID, hash, err := decodePacket(buf)
   611  	if err != nil {
   612  		log.Debug("Bad discv4 packet", "addr", from, "err", err)
   613  		return err
   614  	}
   615  	err = packet.handle(t, from, fromID, hash)
   616  	log.Trace("<< "+packet.name(), "addr", from, "err", err)
   617  	return err
   618  }
   619  
   620  func decodePacket(buf []byte) (packet, NodeID, []byte, error) {
   621  	if len(buf) < headSize+1 {
   622  		return nil, NodeID{}, nil, errPacketTooSmall
   623  	}
   624  	hash, sig, sigdata := buf[:macSize], buf[macSize:headSize], buf[headSize:]
   625  	shouldhash := crypto.Keccak256(buf[macSize:])
   626  	if !bytes.Equal(hash, shouldhash) {
   627  		return nil, NodeID{}, nil, errBadHash
   628  	}
   629  	fromID, err := recoverNodeID(crypto.Keccak256(buf[headSize:]), sig)
   630  	if err != nil {
   631  		return nil, NodeID{}, hash, err
   632  	}
   633  	var req packet
   634  	switch ptype := sigdata[0]; ptype {
   635  	case pingPacket:
   636  		req = new(ping)
   637  	case pongPacket:
   638  		req = new(pong)
   639  	case findnodePacket:
   640  		req = new(findnode)
   641  	case neighborsPacket:
   642  		req = new(neighbors)
   643  	case sendcirclePacket:
   644  		req = new(sendcircle)
   645  	case rtncirclePacket:
   646  		req = new(rtncircle)
   647  	case sendConnectPacket:
   648  		req = new(sendConnect)
   649  	case rtnconnectPacket:
   650  		req = new(rtnConnect)
   651  	case findcirclePacket:
   652  		req = new(findcircle)
   653  	case neighborscirclePacket:
   654  		req = new(neighborscircle)
   655  	case reqPeerOrgPacket:
   656  		req = new(reqPeerOrg)
   657  	case rntPeerOrgPacket:
   658  		req = new(rntPeerOrg)
   659  	case reqPeerConnectPacket:
   660  		req = new(reqPeerConnect)
   661  	case rntPeerConnectPacket:
   662  		req = new(rntPeerConnect)
   663  
   664  	default:
   665  		return nil, fromID, hash, fmt.Errorf("unknown type: %d", ptype)
   666  	}
   667  	s := rlp.NewStream(bytes.NewReader(sigdata[1:]), 0)
   668  	err = s.Decode(req)
   669  	return req, fromID, hash, err
   670  }
   671  
   672  func (req *ping) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) error {
   673  	if expired(req.Expiration) {
   674  		return errExpired
   675  	}
   676  	t.send(from, pongPacket, &pong{
   677  		To:         makeEndpoint(from, req.From.TCP),
   678  		ReplyTok:   mac,
   679  		Expiration: uint64(time.Now().Add(expiration).Unix()),
   680  	})
   681  	if !t.handleReply(fromID, pingPacket, req) {
   682  		// Note: we're ignoring the provided IP address right now
   683  		go t.bond(true, fromID, from, req.From.TCP)
   684  	}
   685  	return nil
   686  }
   687  
   688  func (req *ping) name() string { return "PING/v4" }
   689  
   690  func (req *pong) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) error {
   691  	if expired(req.Expiration) {
   692  		return errExpired
   693  	}
   694  	if !t.handleReply(fromID, pongPacket, req) {
   695  		return errUnsolicitedReply
   696  	}
   697  	return nil
   698  }
   699  
   700  func (req *pong) name() string { return "PONG/v4" }
   701  
   702  func (req *findnode) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) error {
   703  	if expired(req.Expiration) {
   704  		return errExpired
   705  	}
   706  	if t.db.node(fromID) == nil {
   707  		// No bond exists, we don't process the packet. This prevents
   708  		// an attack vector where the discovery protocol could be used
   709  		// to amplify traffic in a DDOS attack. A malicious actor
   710  		// would send a findnode request with the IP address and UDP
   711  		// port of the target as the source address. The recipient of
   712  		// the findnode packet would then send a neighbors packet
   713  		// (which is a much bigger packet than findnode) to the victim.
   714  		return errUnknownNode
   715  	}
   716  	target := crypto.Keccak256Hash(req.Target[:])
   717  	t.mutex.Lock()
   718  	closest := t.closest(target, bucketSize).entries
   719  	t.mutex.Unlock()
   720  
   721  	// test ok
   722  	result := make([]*Node, 0)
   723  	for _, closenode := range closest {
   724  		if t.db.findFails(closenode.ID) == 0 {
   725  			result = append(result, closenode)
   726  		}
   727  	}
   728  
   729  	p := neighbors{
   730  		Expiration: uint64(time.Now().Add(expiration).Unix()),
   731  		Count:      uint64(len(result)),
   732  	}
   733  	// Send neighbors in chunks with at most maxNeighbors per packet
   734  	// to stay below the 1280 byte limit.
   735  	for i, n := range result {
   736  		// if netutil.CheckRelayIP(from.IP, n.IP) != nil {
   737  		// 	continue
   738  		// }
   739  		p.Nodes = append(p.Nodes, nodeToRPC(n))
   740  		if len(p.Nodes) == maxNeighbors || i == len(result)-1 {
   741  			t.send(from, neighborsPacket, &p)
   742  			p.Nodes = p.Nodes[:0]
   743  		}
   744  	}
   745  	return nil
   746  }
   747  
   748  func (req *findnode) name() string { return "FINDNODE/v4" }
   749  
   750  func (req *neighbors) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) error {
   751  	if expired(req.Expiration) {
   752  		return errExpired
   753  	}
   754  	if !t.handleReply(fromID, neighborsPacket, req) {
   755  		return errUnsolicitedReply
   756  	}
   757  	return nil
   758  }
   759  
   760  func (req *neighbors) name() string { return "NEIGHBORS/v4" }
   761  
   762  func expired(ts uint64) bool {
   763  	return time.Unix(int64(ts), 0).Before(time.Now())
   764  }