github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/go-ethereum-master/p2p/protocols/protocol.go (about)

     1  // Copyright 2017 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  /*
    18  Package protocols is an extension to p2p. It offers a user friendly simple way to define
    19  devp2p subprotocols by abstracting away code standardly shared by protocols.
    20  
    21  * automate assigments of code indexes to messages
    22  * automate RLP decoding/encoding based on reflecting
    23  * provide the forever loop to read incoming messages
    24  * standardise error handling related to communication
    25  * standardised	handshake negotiation
    26  * TODO: automatic generation of wire protocol specification for peers
    27  
    28  */
    29  package protocols
    30  
    31  import (
    32  	"context"
    33  	"fmt"
    34  	"io"
    35  	"reflect"
    36  	"sync"
    37  	"time"
    38  
    39  	"github.com/ethereum/go-ethereum/log"
    40  	"github.com/ethereum/go-ethereum/metrics"
    41  	"github.com/ethereum/go-ethereum/p2p"
    42  )
    43  
    44  // error codes used by this  protocol scheme
    45  const (
    46  	ErrMsgTooLong = iota
    47  	ErrDecode
    48  	ErrWrite
    49  	ErrInvalidMsgCode
    50  	ErrInvalidMsgType
    51  	ErrHandshake
    52  	ErrNoHandler
    53  	ErrHandler
    54  )
    55  
    56  // error description strings associated with the codes
    57  var errorToString = map[int]string{
    58  	ErrMsgTooLong:     "Message too long",
    59  	ErrDecode:         "Invalid message (RLP error)",
    60  	ErrWrite:          "Error sending message",
    61  	ErrInvalidMsgCode: "Invalid message code",
    62  	ErrInvalidMsgType: "Invalid message type",
    63  	ErrHandshake:      "Handshake error",
    64  	ErrNoHandler:      "No handler registered error",
    65  	ErrHandler:        "Message handler error",
    66  }
    67  
    68  /*
    69  Error implements the standard go error interface.
    70  Use:
    71  
    72    errorf(code, format, params ...interface{})
    73  
    74  Prints as:
    75  
    76   <description>: <details>
    77  
    78  where description is given by code in errorToString
    79  and details is fmt.Sprintf(format, params...)
    80  
    81  exported field Code can be checked
    82  */
    83  type Error struct {
    84  	Code    int
    85  	message string
    86  	format  string
    87  	params  []interface{}
    88  }
    89  
    90  func (e Error) Error() (message string) {
    91  	if len(e.message) == 0 {
    92  		name, ok := errorToString[e.Code]
    93  		if !ok {
    94  			panic("invalid message code")
    95  		}
    96  		e.message = name
    97  		if e.format != "" {
    98  			e.message += ": " + fmt.Sprintf(e.format, e.params...)
    99  		}
   100  	}
   101  	return e.message
   102  }
   103  
   104  func errorf(code int, format string, params ...interface{}) *Error {
   105  	return &Error{
   106  		Code:   code,
   107  		format: format,
   108  		params: params,
   109  	}
   110  }
   111  
   112  // Spec is a protocol specification including its name and version as well as
   113  // the types of messages which are exchanged
   114  type Spec struct {
   115  	// Name is the name of the protocol, often a three-letter word
   116  	Name string
   117  
   118  	// Version is the version number of the protocol
   119  	Version uint
   120  
   121  	// MaxMsgSize is the maximum accepted length of the message payload
   122  	MaxMsgSize uint32
   123  
   124  	// Messages is a list of message data types which this protocol uses, with
   125  	// each message type being sent with its array index as the code (so
   126  	// [&foo{}, &bar{}, &baz{}] would send foo, bar and baz with codes
   127  	// 0, 1 and 2 respectively)
   128  	// each message must have a single unique data type
   129  	Messages []interface{}
   130  
   131  	initOnce sync.Once
   132  	codes    map[reflect.Type]uint64
   133  	types    map[uint64]reflect.Type
   134  }
   135  
   136  func (s *Spec) init() {
   137  	s.initOnce.Do(func() {
   138  		s.codes = make(map[reflect.Type]uint64, len(s.Messages))
   139  		s.types = make(map[uint64]reflect.Type, len(s.Messages))
   140  		for i, msg := range s.Messages {
   141  			code := uint64(i)
   142  			typ := reflect.TypeOf(msg)
   143  			if typ.Kind() == reflect.Ptr {
   144  				typ = typ.Elem()
   145  			}
   146  			s.codes[typ] = code
   147  			s.types[code] = typ
   148  		}
   149  	})
   150  }
   151  
   152  // Length returns the number of message types in the protocol
   153  func (s *Spec) Length() uint64 {
   154  	return uint64(len(s.Messages))
   155  }
   156  
   157  // GetCode returns the message code of a type, and boolean second argument is
   158  // false if the message type is not found
   159  func (s *Spec) GetCode(msg interface{}) (uint64, bool) {
   160  	s.init()
   161  	typ := reflect.TypeOf(msg)
   162  	if typ.Kind() == reflect.Ptr {
   163  		typ = typ.Elem()
   164  	}
   165  	code, ok := s.codes[typ]
   166  	return code, ok
   167  }
   168  
   169  // NewMsg construct a new message type given the code
   170  func (s *Spec) NewMsg(code uint64) (interface{}, bool) {
   171  	s.init()
   172  	typ, ok := s.types[code]
   173  	if !ok {
   174  		return nil, false
   175  	}
   176  	return reflect.New(typ).Interface(), true
   177  }
   178  
   179  // Peer represents a remote peer or protocol instance that is running on a peer connection with
   180  // a remote peer
   181  type Peer struct {
   182  	*p2p.Peer                   // the p2p.Peer object representing the remote
   183  	rw        p2p.MsgReadWriter // p2p.MsgReadWriter to send messages to and read messages from
   184  	spec      *Spec
   185  }
   186  
   187  // NewPeer constructs a new peer
   188  // this constructor is called by the p2p.Protocol#Run function
   189  // the first two arguments are the arguments passed to p2p.Protocol.Run function
   190  // the third argument is the Spec describing the protocol
   191  func NewPeer(p *p2p.Peer, rw p2p.MsgReadWriter, spec *Spec) *Peer {
   192  	return &Peer{
   193  		Peer: p,
   194  		rw:   rw,
   195  		spec: spec,
   196  	}
   197  }
   198  
   199  // Run starts the forever loop that handles incoming messages
   200  // called within the p2p.Protocol#Run function
   201  // the handler argument is a function which is called for each message received
   202  // from the remote peer, a returned error causes the loop to exit
   203  // resulting in disconnection
   204  func (p *Peer) Run(handler func(msg interface{}) error) error {
   205  	for {
   206  		if err := p.handleIncoming(handler); err != nil {
   207  			if err != io.EOF {
   208  				metrics.GetOrRegisterCounter("peer.handleincoming.error", nil).Inc(1)
   209  				log.Error("peer.handleIncoming", "err", err)
   210  			}
   211  
   212  			return err
   213  		}
   214  	}
   215  }
   216  
   217  // Drop disconnects a peer.
   218  // TODO: may need to implement protocol drop only? don't want to kick off the peer
   219  // if they are useful for other protocols
   220  func (p *Peer) Drop(err error) {
   221  	p.Disconnect(p2p.DiscSubprotocolError)
   222  }
   223  
   224  // Send takes a message, encodes it in RLP, finds the right message code and sends the
   225  // message off to the peer
   226  // this low level call will be wrapped by libraries providing routed or broadcast sends
   227  // but often just used to forward and push messages to directly connected peers
   228  func (p *Peer) Send(msg interface{}) error {
   229  	defer metrics.GetOrRegisterResettingTimer("peer.send_t", nil).UpdateSince(time.Now())
   230  	metrics.GetOrRegisterCounter("peer.send", nil).Inc(1)
   231  	code, found := p.spec.GetCode(msg)
   232  	if !found {
   233  		return errorf(ErrInvalidMsgType, "%v", code)
   234  	}
   235  	return p2p.Send(p.rw, code, msg)
   236  }
   237  
   238  // handleIncoming(code)
   239  // is called each cycle of the main forever loop that dispatches incoming messages
   240  // if this returns an error the loop returns and the peer is disconnected with the error
   241  // this generic handler
   242  // * checks message size,
   243  // * checks for out-of-range message codes,
   244  // * handles decoding with reflection,
   245  // * call handlers as callbacks
   246  func (p *Peer) handleIncoming(handle func(msg interface{}) error) error {
   247  	msg, err := p.rw.ReadMsg()
   248  	if err != nil {
   249  		return err
   250  	}
   251  	// make sure that the payload has been fully consumed
   252  	defer msg.Discard()
   253  
   254  	if msg.Size > p.spec.MaxMsgSize {
   255  		return errorf(ErrMsgTooLong, "%v > %v", msg.Size, p.spec.MaxMsgSize)
   256  	}
   257  
   258  	val, ok := p.spec.NewMsg(msg.Code)
   259  	if !ok {
   260  		return errorf(ErrInvalidMsgCode, "%v", msg.Code)
   261  	}
   262  	if err := msg.Decode(val); err != nil {
   263  		return errorf(ErrDecode, "<= %v: %v", msg, err)
   264  	}
   265  
   266  	// call the registered handler callbacks
   267  	// a registered callback take the decoded message as argument as an interface
   268  	// which the handler is supposed to cast to the appropriate type
   269  	// it is entirely safe not to check the cast in the handler since the handler is
   270  	// chosen based on the proper type in the first place
   271  	if err := handle(val); err != nil {
   272  		return errorf(ErrHandler, "(msg code %v): %v", msg.Code, err)
   273  	}
   274  	return nil
   275  }
   276  
   277  // Handshake negotiates a handshake on the peer connection
   278  // * arguments
   279  //   * context
   280  //   * the local handshake to be sent to the remote peer
   281  //   * funcion to be called on the remote handshake (can be nil)
   282  // * expects a remote handshake back of the same type
   283  // * the dialing peer needs to send the handshake first and then waits for remote
   284  // * the listening peer waits for the remote handshake and then sends it
   285  // returns the remote handshake and an error
   286  func (p *Peer) Handshake(ctx context.Context, hs interface{}, verify func(interface{}) error) (rhs interface{}, err error) {
   287  	if _, ok := p.spec.GetCode(hs); !ok {
   288  		return nil, errorf(ErrHandshake, "unknown handshake message type: %T", hs)
   289  	}
   290  	errc := make(chan error, 2)
   291  	handle := func(msg interface{}) error {
   292  		rhs = msg
   293  		if verify != nil {
   294  			return verify(rhs)
   295  		}
   296  		return nil
   297  	}
   298  	send := func() { errc <- p.Send(hs) }
   299  	receive := func() { errc <- p.handleIncoming(handle) }
   300  
   301  	go func() {
   302  		if p.Inbound() {
   303  			receive()
   304  			send()
   305  		} else {
   306  			send()
   307  			receive()
   308  		}
   309  	}()
   310  
   311  	for i := 0; i < 2; i++ {
   312  		select {
   313  		case err = <-errc:
   314  		case <-ctx.Done():
   315  			err = ctx.Err()
   316  		}
   317  		if err != nil {
   318  			return nil, errorf(ErrHandshake, err.Error())
   319  		}
   320  	}
   321  	return rhs, nil
   322  }