github.com/jimmyx0x/go-ethereum@v1.10.28/p2p/discover/v5wire/msg.go (about)

     1  // Copyright 2020 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 v5wire
    18  
    19  import (
    20  	"fmt"
    21  	"net"
    22  
    23  	"github.com/ethereum/go-ethereum/common/hexutil"
    24  	"github.com/ethereum/go-ethereum/common/mclock"
    25  	"github.com/ethereum/go-ethereum/p2p/enode"
    26  	"github.com/ethereum/go-ethereum/p2p/enr"
    27  	"github.com/ethereum/go-ethereum/rlp"
    28  )
    29  
    30  // Packet is implemented by all message types.
    31  type Packet interface {
    32  	Name() string        // Name returns a string corresponding to the message type.
    33  	Kind() byte          // Kind returns the message type.
    34  	RequestID() []byte   // Returns the request ID.
    35  	SetRequestID([]byte) // Sets the request ID.
    36  
    37  	// AppendLogInfo returns its argument 'ctx' with additional fields
    38  	// appended for logging purposes.
    39  	AppendLogInfo(ctx []interface{}) []interface{}
    40  }
    41  
    42  // Message types.
    43  const (
    44  	PingMsg byte = iota + 1
    45  	PongMsg
    46  	FindnodeMsg
    47  	NodesMsg
    48  	TalkRequestMsg
    49  	TalkResponseMsg
    50  	RequestTicketMsg
    51  	TicketMsg
    52  
    53  	UnknownPacket   = byte(255) // any non-decryptable packet
    54  	WhoareyouPacket = byte(254) // the WHOAREYOU packet
    55  )
    56  
    57  // Protocol messages.
    58  type (
    59  	// Unknown represents any packet that can't be decrypted.
    60  	Unknown struct {
    61  		Nonce Nonce
    62  	}
    63  
    64  	// WHOAREYOU contains the handshake challenge.
    65  	Whoareyou struct {
    66  		ChallengeData []byte   // Encoded challenge
    67  		Nonce         Nonce    // Nonce of request packet
    68  		IDNonce       [16]byte // Identity proof data
    69  		RecordSeq     uint64   // ENR sequence number of recipient
    70  
    71  		// Node is the locally known node record of recipient.
    72  		// This must be set by the caller of Encode.
    73  		Node *enode.Node
    74  
    75  		sent mclock.AbsTime // for handshake GC.
    76  	}
    77  
    78  	// PING is sent during liveness checks.
    79  	Ping struct {
    80  		ReqID  []byte
    81  		ENRSeq uint64
    82  	}
    83  
    84  	// PONG is the reply to PING.
    85  	Pong struct {
    86  		ReqID  []byte
    87  		ENRSeq uint64
    88  		ToIP   net.IP // These fields should mirror the UDP envelope address of the ping
    89  		ToPort uint16 // packet, which provides a way to discover the external address (after NAT).
    90  	}
    91  
    92  	// FINDNODE is a query for nodes in the given bucket.
    93  	Findnode struct {
    94  		ReqID     []byte
    95  		Distances []uint
    96  
    97  		// OpID is for debugging purposes and is not part of the packet encoding.
    98  		// It identifies the 'operation' on behalf of which the request was sent.
    99  		OpID uint64 `rlp:"-"`
   100  	}
   101  
   102  	// NODES is a response to FINDNODE.
   103  	Nodes struct {
   104  		ReqID     []byte
   105  		RespCount uint8 // total number of responses to the request
   106  		Nodes     []*enr.Record
   107  	}
   108  
   109  	// TALKREQ is an application-level request.
   110  	TalkRequest struct {
   111  		ReqID    []byte
   112  		Protocol string
   113  		Message  []byte
   114  	}
   115  
   116  	// TALKRESP is the reply to TALKREQ.
   117  	TalkResponse struct {
   118  		ReqID   []byte
   119  		Message []byte
   120  	}
   121  )
   122  
   123  // DecodeMessage decodes the message body of a packet.
   124  func DecodeMessage(ptype byte, body []byte) (Packet, error) {
   125  	var dec Packet
   126  	switch ptype {
   127  	case PingMsg:
   128  		dec = new(Ping)
   129  	case PongMsg:
   130  		dec = new(Pong)
   131  	case FindnodeMsg:
   132  		dec = new(Findnode)
   133  	case NodesMsg:
   134  		dec = new(Nodes)
   135  	case TalkRequestMsg:
   136  		dec = new(TalkRequest)
   137  	case TalkResponseMsg:
   138  		dec = new(TalkResponse)
   139  	default:
   140  		return nil, fmt.Errorf("unknown packet type %d", ptype)
   141  	}
   142  	if err := rlp.DecodeBytes(body, dec); err != nil {
   143  		return nil, err
   144  	}
   145  	if dec.RequestID() != nil && len(dec.RequestID()) > 8 {
   146  		return nil, ErrInvalidReqID
   147  	}
   148  	return dec, nil
   149  }
   150  
   151  func (*Whoareyou) Name() string        { return "WHOAREYOU/v5" }
   152  func (*Whoareyou) Kind() byte          { return WhoareyouPacket }
   153  func (*Whoareyou) RequestID() []byte   { return nil }
   154  func (*Whoareyou) SetRequestID([]byte) {}
   155  
   156  func (*Whoareyou) AppendLogInfo(ctx []interface{}) []interface{} {
   157  	return ctx
   158  }
   159  
   160  func (*Unknown) Name() string        { return "UNKNOWN/v5" }
   161  func (*Unknown) Kind() byte          { return UnknownPacket }
   162  func (*Unknown) RequestID() []byte   { return nil }
   163  func (*Unknown) SetRequestID([]byte) {}
   164  
   165  func (*Unknown) AppendLogInfo(ctx []interface{}) []interface{} {
   166  	return ctx
   167  }
   168  
   169  func (*Ping) Name() string             { return "PING/v5" }
   170  func (*Ping) Kind() byte               { return PingMsg }
   171  func (p *Ping) RequestID() []byte      { return p.ReqID }
   172  func (p *Ping) SetRequestID(id []byte) { p.ReqID = id }
   173  
   174  func (p *Ping) AppendLogInfo(ctx []interface{}) []interface{} {
   175  	return append(ctx, "req", hexutil.Bytes(p.ReqID), "enrseq", p.ENRSeq)
   176  }
   177  
   178  func (*Pong) Name() string             { return "PONG/v5" }
   179  func (*Pong) Kind() byte               { return PongMsg }
   180  func (p *Pong) RequestID() []byte      { return p.ReqID }
   181  func (p *Pong) SetRequestID(id []byte) { p.ReqID = id }
   182  
   183  func (p *Pong) AppendLogInfo(ctx []interface{}) []interface{} {
   184  	return append(ctx, "req", hexutil.Bytes(p.ReqID), "enrseq", p.ENRSeq)
   185  }
   186  
   187  func (p *Findnode) Name() string           { return "FINDNODE/v5" }
   188  func (p *Findnode) Kind() byte             { return FindnodeMsg }
   189  func (p *Findnode) RequestID() []byte      { return p.ReqID }
   190  func (p *Findnode) SetRequestID(id []byte) { p.ReqID = id }
   191  
   192  func (p *Findnode) AppendLogInfo(ctx []interface{}) []interface{} {
   193  	ctx = append(ctx, "req", hexutil.Bytes(p.ReqID))
   194  	if p.OpID != 0 {
   195  		ctx = append(ctx, "opid", p.OpID)
   196  	}
   197  	return ctx
   198  }
   199  
   200  func (*Nodes) Name() string             { return "NODES/v5" }
   201  func (*Nodes) Kind() byte               { return NodesMsg }
   202  func (p *Nodes) RequestID() []byte      { return p.ReqID }
   203  func (p *Nodes) SetRequestID(id []byte) { p.ReqID = id }
   204  
   205  func (p *Nodes) AppendLogInfo(ctx []interface{}) []interface{} {
   206  	return append(ctx,
   207  		"req", hexutil.Bytes(p.ReqID),
   208  		"tot", p.RespCount,
   209  		"n", len(p.Nodes),
   210  	)
   211  }
   212  
   213  func (*TalkRequest) Name() string             { return "TALKREQ/v5" }
   214  func (*TalkRequest) Kind() byte               { return TalkRequestMsg }
   215  func (p *TalkRequest) RequestID() []byte      { return p.ReqID }
   216  func (p *TalkRequest) SetRequestID(id []byte) { p.ReqID = id }
   217  
   218  func (p *TalkRequest) AppendLogInfo(ctx []interface{}) []interface{} {
   219  	return append(ctx, "proto", p.Protocol, "reqid", hexutil.Bytes(p.ReqID), "len", len(p.Message))
   220  }
   221  
   222  func (*TalkResponse) Name() string             { return "TALKRESP/v5" }
   223  func (*TalkResponse) Kind() byte               { return TalkResponseMsg }
   224  func (p *TalkResponse) RequestID() []byte      { return p.ReqID }
   225  func (p *TalkResponse) SetRequestID(id []byte) { p.ReqID = id }
   226  
   227  func (p *TalkResponse) AppendLogInfo(ctx []interface{}) []interface{} {
   228  	return append(ctx, "req", p.ReqID, "len", len(p.Message))
   229  }