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 }