- package p2p
-
- import (
- "fmt"
- "io"
- "net"
- "sync/atomic"
-
- "github.com/tendermint/tendermint/binary"
- . "github.com/tendermint/tendermint/common"
- "github.com/tendermint/tendermint/types"
- )
-
- type Peer struct {
- outbound bool
- mconn *MConnection
- running uint32
-
- *types.NodeInfo
- Key string
- Data *CMap // User data.
- }
-
- // NOTE: blocking
- // Before creating a peer with newPeer(), perform a handshake on connection.
- func peerHandshake(conn net.Conn, ourNodeInfo *types.NodeInfo) (*types.NodeInfo, error) {
- var peerNodeInfo = new(types.NodeInfo)
- var err1 error
- var err2 error
- Parallel(
- func() {
- var n int64
- binary.WriteBinary(ourNodeInfo, conn, &n, &err1)
- },
- func() {
- var n int64
- binary.ReadBinary(peerNodeInfo, conn, &n, &err2)
- log.Info("Peer handshake", "peerNodeInfo", peerNodeInfo)
- })
- if err1 != nil {
- return nil, err1
- }
- if err2 != nil {
- return nil, err2
- }
- return peerNodeInfo, nil
- }
-
- // NOTE: call peerHandshake on conn before calling newPeer().
- func newPeer(conn net.Conn, peerNodeInfo *types.NodeInfo, outbound bool, reactorsByCh map[byte]Reactor, chDescs []*ChannelDescriptor, onPeerError func(*Peer, interface{})) *Peer {
- var p *Peer
- onReceive := func(chId byte, msgBytes []byte) {
- reactor := reactorsByCh[chId]
- if reactor == nil {
- panic(Fmt("Unknown channel %X", chId))
- }
- reactor.Receive(chId, p, msgBytes)
- }
- onError := func(r interface{}) {
- p.stop()
- onPeerError(p, r)
- }
- mconn := NewMConnection(conn, chDescs, onReceive, onError)
- p = &Peer{
- outbound: outbound,
- mconn: mconn,
- running: 0,
- NodeInfo: peerNodeInfo,
- Key: peerNodeInfo.UUID,
- Data: NewCMap(),
- }
- return p
- }
-
- func (p *Peer) start() {
- if atomic.CompareAndSwapUint32(&p.running, 0, 1) {
- log.Debug("Starting Peer", "peer", p)
- p.mconn.Start()
- }
- }
-
- func (p *Peer) stop() {
- if atomic.CompareAndSwapUint32(&p.running, 1, 0) {
- log.Debug("Stopping Peer", "peer", p)
- p.mconn.Stop()
- }
- }
-
- func (p *Peer) IsRunning() bool {
- return atomic.LoadUint32(&p.running) == 1
- }
-
- func (p *Peer) Connection() *MConnection {
- return p.mconn
- }
-
- func (p *Peer) IsOutbound() bool {
- return p.outbound
- }
-
- func (p *Peer) Send(chId byte, msg interface{}) bool {
- if atomic.LoadUint32(&p.running) == 0 {
- return false
- }
- return p.mconn.Send(chId, msg)
- }
-
- func (p *Peer) TrySend(chId byte, msg interface{}) bool {
- if atomic.LoadUint32(&p.running) == 0 {
- return false
- }
- return p.mconn.TrySend(chId, msg)
- }
-
- func (p *Peer) CanSend(chId byte) bool {
- if atomic.LoadUint32(&p.running) == 0 {
- return false
- }
- return p.mconn.CanSend(chId)
- }
-
- func (p *Peer) WriteTo(w io.Writer) (n int64, err error) {
- binary.WriteString(p.Key, w, &n, &err)
- return
- }
-
- func (p *Peer) String() string {
- if p.outbound {
- return fmt.Sprintf("Peer{->%v}", p.mconn)
- } else {
- return fmt.Sprintf("Peer{%v->}", p.mconn)
- }
- }
-
- func (p *Peer) Equals(other *Peer) bool {
- return p.Key == other.Key
- }
|