code: func (p *Peer) Send(ctx context.Context, msg interface{}) error {
  	defer metrics.GetOrRegisterResettingTimer("peer.send_t", nil).UpdateSince(time.Now())
  	metrics.GetOrRegisterCounter("peer.send", nil).Inc(1)
  
  	var b bytes.Buffer
  	if tracing.Enabled {
  		writer := bufio.NewWriter(&b)
  
  		tracer := opentracing.GlobalTracer()
  
  		sctx := spancontext.FromContext(ctx)
  
  		if sctx != nil {
  			err := tracer.Inject(
  				sctx,
  				opentracing.Binary,
  				writer)
  			if err != nil {
  				return err
  			}
  		}
  
  		writer.Flush()
  	}
  
  	r, err := rlp.EncodeToBytes(msg)
  	if err != nil {
  		return err
  	}
  
  	wmsg := WrappedMsg{
  		Context: b.Bytes(),
  		Size:    uint32(len(r)),
  		Payload: r,
  	}
  
  	//if the accounting hook is set, call it
  	if p.spec.Hook != nil {
  		err := p.spec.Hook.Send(p, wmsg.Size, msg)
  		if err != nil {
  			p.Drop(err)
  			return err
  		}
  	}
  
  	code, found := p.spec.GetCode(msg)
  	if !found {
  		return errorf(ErrInvalidMsgType, "%v", code)
  	}
  	return p2p.Send(p.rw, code, wmsg)
  }
docs: // Send takes a message, encodes it in RLP, finds the right message code and sends the
  // message off to the peer
  // this low level call will be wrapped by libraries providing routed or broadcast sends
  // but often just used to forward and push messages to directly connected peers