OSDN Git Service

edit the remoteAddr
[bytom/bytom.git] / p2p / peer.go
index 8d8580e..d1e6331 100644 (file)
@@ -2,7 +2,6 @@ package p2p
 
 import (
        "fmt"
-       "io"
        "net"
        "time"
 
@@ -13,23 +12,23 @@ import (
        cmn "github.com/tendermint/tmlibs/common"
 
        cfg "github.com/bytom/config"
+       "github.com/bytom/p2p/connection"
 )
 
-// Peer could be marked as persistent, in which case you can use
-// Redial function to reconnect. Note that inbound peers can't be
-// made persistent. They should be made persistent on the other end.
-//
-// Before using a peer, you will need to perform a handshake on connection.
-type Peer struct {
-       cmn.BaseService
-
+// peerConn contains the raw connection and its config.
+type peerConn struct {
        outbound bool
+       config   *PeerConfig
+       conn     net.Conn // source connection
+}
 
-       conn  net.Conn     // source connection
-       mconn *MConnection // multiplex connection
+// Peer represent a bytom network node
+type Peer struct {
+       cmn.BaseService
 
-       persistent bool
-       config     *PeerConfig
+       // raw peerConn and the multiplex connection
+       *peerConn
+       mconn *connection.MConnection // multiplex connection
 
        *NodeInfo
        Key  string
@@ -44,7 +43,7 @@ type PeerConfig struct {
        HandshakeTimeout time.Duration `mapstructure:"handshake_timeout"`
        DialTimeout      time.Duration `mapstructure:"dial_timeout"`
 
-       MConfig *MConnConfig `mapstructure:"connection"`
+       MConfig *connection.MConnConfig `mapstructure:"connection"`
 
        Fuzz       bool            `mapstructure:"fuzz"` // fuzz connection (for testing)
        FuzzConfig *FuzzConnConfig `mapstructure:"fuzz_config"`
@@ -55,40 +54,52 @@ func DefaultPeerConfig(config *cfg.P2PConfig) *PeerConfig {
        return &PeerConfig{
                AuthEnc:          true,
                HandshakeTimeout: time.Duration(config.HandshakeTimeout), // * time.Second,
-               DialTimeout:      time.Duration(config.DialTimeout),  // * time.Second,
-               MConfig:          DefaultMConnConfig(),
+               DialTimeout:      time.Duration(config.DialTimeout),      // * time.Second,
+               MConfig:          connection.DefaultMConnConfig(),
                Fuzz:             false,
                FuzzConfig:       DefaultFuzzConnConfig(),
        }
 }
 
-func newOutboundPeer(addr *NetAddress, reactorsByCh map[byte]Reactor, chDescs []*ChannelDescriptor, onPeerError func(*Peer, interface{}), ourNodePrivKey crypto.PrivKeyEd25519, config *cfg.P2PConfig) (*Peer, error) {
-       return newOutboundPeerWithConfig(addr, reactorsByCh, chDescs, onPeerError, ourNodePrivKey, DefaultPeerConfig(config))
+func newPeer(pc *peerConn, nodeInfo *NodeInfo, reactorsByCh map[byte]Reactor, chDescs []*connection.ChannelDescriptor, onPeerError func(*Peer, interface{})) *Peer {
+       // Key and NodeInfo are set after Handshake
+       p := &Peer{
+               peerConn: pc,
+               NodeInfo: nodeInfo,
+
+               Data: cmn.NewCMap(),
+       }
+       p.Key = nodeInfo.PubKey.KeyString()
+       p.mconn = createMConnection(pc.conn, p, reactorsByCh, chDescs, onPeerError, pc.config.MConfig)
+
+       p.BaseService = *cmn.NewBaseService(nil, "Peer", p)
+       return p
+}
+
+func newOutboundPeer(addr *NetAddress, reactorsByCh map[byte]Reactor, chDescs []*connection.ChannelDescriptor, onPeerError func(*Peer, interface{}), ourNodePrivKey crypto.PrivKeyEd25519, config *cfg.P2PConfig) (*peerConn, error) {
+       return newOutboundPeerConn(addr, reactorsByCh, chDescs, onPeerError, ourNodePrivKey, DefaultPeerConfig(config))
 }
 
-func newOutboundPeerWithConfig(addr *NetAddress, reactorsByCh map[byte]Reactor, chDescs []*ChannelDescriptor, onPeerError func(*Peer, interface{}), ourNodePrivKey crypto.PrivKeyEd25519, config *PeerConfig) (*Peer, error) {
+func newOutboundPeerConn(addr *NetAddress, reactorsByCh map[byte]Reactor, chDescs []*connection.ChannelDescriptor, onPeerError func(*Peer, interface{}), ourNodePrivKey crypto.PrivKeyEd25519, config *PeerConfig) (*peerConn, error) {
        conn, err := dial(addr, config)
        if err != nil {
-               return nil, errors.Wrap(err, "Error creating peer")
+               return nil, errors.Wrap(err, "Error dial peer")
        }
 
-       peer, err := newPeerFromConnAndConfig(conn, true, reactorsByCh, chDescs, onPeerError, ourNodePrivKey, config)
+       pc, err := newPeerConn(conn, true, reactorsByCh, chDescs, onPeerError, ourNodePrivKey, config)
        if err != nil {
                conn.Close()
                return nil, err
        }
-       return peer, nil
-}
 
-func newInboundPeer(conn net.Conn, reactorsByCh map[byte]Reactor, chDescs []*ChannelDescriptor, onPeerError func(*Peer, interface{}), ourNodePrivKey crypto.PrivKeyEd25519, config *cfg.P2PConfig) (*Peer, error) {
-       return newInboundPeerWithConfig(conn, reactorsByCh, chDescs, onPeerError, ourNodePrivKey, DefaultPeerConfig(config))
+       return pc, nil
 }
 
-func newInboundPeerWithConfig(conn net.Conn, reactorsByCh map[byte]Reactor, chDescs []*ChannelDescriptor, onPeerError func(*Peer, interface{}), ourNodePrivKey crypto.PrivKeyEd25519, config *PeerConfig) (*Peer, error) {
-       return newPeerFromConnAndConfig(conn, false, reactorsByCh, chDescs, onPeerError, ourNodePrivKey, config)
+func newInboundPeerConn(conn net.Conn, reactorsByCh map[byte]Reactor, chDescs []*connection.ChannelDescriptor, onPeerError func(*Peer, interface{}), ourNodePrivKey crypto.PrivKeyEd25519, config *cfg.P2PConfig) (*peerConn, error) {
+       return newPeerConn(conn, false, reactorsByCh, chDescs, onPeerError, ourNodePrivKey, DefaultPeerConfig(config))
 }
 
-func newPeerFromConnAndConfig(rawConn net.Conn, outbound bool, reactorsByCh map[byte]Reactor, chDescs []*ChannelDescriptor, onPeerError func(*Peer, interface{}), ourNodePrivKey crypto.PrivKeyEd25519, config *PeerConfig) (*Peer, error) {
+func newPeerConn(rawConn net.Conn, outbound bool, reactorsByCh map[byte]Reactor, chDescs []*connection.ChannelDescriptor, onPeerError func(*Peer, interface{}), ourNodePrivKey crypto.PrivKeyEd25519, config *PeerConfig) (*peerConn, error) {
        conn := rawConn
 
        // Fuzz connection
@@ -102,51 +113,30 @@ func newPeerFromConnAndConfig(rawConn net.Conn, outbound bool, reactorsByCh map[
                conn.SetDeadline(time.Now().Add(config.HandshakeTimeout * time.Second))
 
                var err error
-               conn, err = MakeSecretConnection(conn, ourNodePrivKey)
+               conn, err = connection.MakeSecretConnection(conn, ourNodePrivKey)
                if err != nil {
                        return nil, errors.Wrap(err, "Error creating peer")
                }
        }
 
-       // Key and NodeInfo are set after Handshake
-       p := &Peer{
+       // Only the information we already have
+       return &peerConn{
+               config:   config,
                outbound: outbound,
                conn:     conn,
-               config:   config,
-               Data:     cmn.NewCMap(),
-       }
-
-       p.mconn = createMConnection(conn, p, reactorsByCh, chDescs, onPeerError, config.MConfig)
-
-       p.BaseService = *cmn.NewBaseService(nil, "Peer", p)
-
-       return p, nil
+       }, nil
 }
 
 // CloseConn should be used when the peer was created, but never started.
-func (p *Peer) CloseConn() {
-       p.conn.Close()
-}
-
-// makePersistent marks the peer as persistent.
-func (p *Peer) makePersistent() {
-       if !p.outbound {
-               panic("inbound peers can't be made persistent")
-       }
-
-       p.persistent = true
-}
-
-// IsPersistent returns true if the peer is persitent, false otherwise.
-func (p *Peer) IsPersistent() bool {
-       return p.persistent
+func (pc *peerConn) CloseConn() {
+       pc.conn.Close()
 }
 
 // HandshakeTimeout performs a handshake between a given node and the peer.
 // NOTE: blocking
-func (p *Peer) HandshakeTimeout(ourNodeInfo *NodeInfo, timeout time.Duration) error {
+func (pc *peerConn) HandshakeTimeout(ourNodeInfo *NodeInfo, timeout time.Duration) (*NodeInfo, error) {
        // Set deadline for handshake so we don't block forever on conn.ReadFull
-       p.conn.SetDeadline(time.Now().Add(timeout))
+       pc.conn.SetDeadline(time.Now().Add(timeout))
 
        var peerNodeInfo = new(NodeInfo)
        var err1 error
@@ -154,37 +144,24 @@ func (p *Peer) HandshakeTimeout(ourNodeInfo *NodeInfo, timeout time.Duration) er
        cmn.Parallel(
                func() {
                        var n int
-                       wire.WriteBinary(ourNodeInfo, p.conn, &n, &err1)
+                       wire.WriteBinary(ourNodeInfo, pc.conn, &n, &err1)
                },
                func() {
                        var n int
-                       wire.ReadBinary(peerNodeInfo, p.conn, maxNodeInfoSize, &n, &err2)
+                       wire.ReadBinary(peerNodeInfo, pc.conn, maxNodeInfoSize, &n, &err2)
                        log.WithField("peerNodeInfo", peerNodeInfo).Info("Peer handshake")
                })
        if err1 != nil {
-               return errors.Wrap(err1, "Error during handshake/write")
+               return peerNodeInfo, errors.Wrap(err1, "Error during handshake/write")
        }
        if err2 != nil {
-               return errors.Wrap(err2, "Error during handshake/read")
-       }
-
-       if p.config.AuthEnc {
-               // Check that the professed PubKey matches the sconn's.
-               if !peerNodeInfo.PubKey.Equals(p.PubKey().Wrap()) {
-                       return fmt.Errorf("Ignoring connection with unmatching pubkey: %v vs %v",
-                               peerNodeInfo.PubKey, p.PubKey())
-               }
+               return peerNodeInfo, errors.Wrap(err2, "Error during handshake/read")
        }
 
        // Remove deadline
-       p.conn.SetDeadline(time.Time{})
-
-       peerNodeInfo.RemoteAddr = p.Addr().String()
-
-       p.NodeInfo = peerNodeInfo
-       p.Key = peerNodeInfo.PubKey.KeyString()
-
-       return nil
+       pc.conn.SetDeadline(time.Time{})
+       peerNodeInfo.RemoteAddr = pc.conn.RemoteAddr().String()
+       return peerNodeInfo, nil
 }
 
 // Addr returns peer's remote network address.
@@ -195,7 +172,7 @@ func (p *Peer) Addr() net.Addr {
 // PubKey returns peer's public key.
 func (p *Peer) PubKey() crypto.PubKeyEd25519 {
        if p.config.AuthEnc {
-               return p.conn.(*SecretConnection).RemotePubKey()
+               return p.conn.(*connection.SecretConnection).RemotePubKey()
        }
        if p.NodeInfo == nil {
                panic("Attempt to get peer's PubKey before calling Handshake")
@@ -217,7 +194,7 @@ func (p *Peer) OnStop() {
 }
 
 // Connection returns underlying MConnection.
-func (p *Peer) Connection() *MConnection {
+func (p *Peer) Connection() *connection.MConnection {
        return p.mconn
 }
 
@@ -254,14 +231,6 @@ func (p *Peer) CanSend(chID byte) bool {
        return p.mconn.CanSend(chID)
 }
 
-// WriteTo writes the peer's public key to w.
-func (p *Peer) WriteTo(w io.Writer) (n int64, err error) {
-       var n_ int
-       wire.WriteString(p.Key, w, &n_, &err)
-       n += int64(n_)
-       return
-}
-
 // String representation.
 func (p *Peer) String() string {
        if p.outbound {
@@ -289,7 +258,7 @@ func dial(addr *NetAddress, config *PeerConfig) (net.Conn, error) {
        return conn, nil
 }
 
-func createMConnection(conn net.Conn, p *Peer, reactorsByCh map[byte]Reactor, chDescs []*ChannelDescriptor, onPeerError func(*Peer, interface{}), config *MConnConfig) *MConnection {
+func createMConnection(conn net.Conn, p *Peer, reactorsByCh map[byte]Reactor, chDescs []*connection.ChannelDescriptor, onPeerError func(*Peer, interface{}), config *connection.MConnConfig) *connection.MConnection {
        onReceive := func(chID byte, msgBytes []byte) {
                reactor := reactorsByCh[chID]
                if reactor == nil {
@@ -302,5 +271,5 @@ func createMConnection(conn net.Conn, p *Peer, reactorsByCh map[byte]Reactor, ch
                onPeerError(p, r)
        }
 
-       return NewMConnectionWithConfig(conn, chDescs, onReceive, onError, config)
+       return connection.NewMConnectionWithConfig(conn, chDescs, onReceive, onError, config)
 }