github.com/klaytn/klaytn@v1.12.1/networks/p2p/discover/udp.go (about)

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