2014-07-07 20:03:50 -07:00
|
|
|
package p2p
|
2014-06-18 20:48:32 -07:00
|
|
|
|
|
|
|
import (
|
2014-07-01 14:50:24 -07:00
|
|
|
"fmt"
|
|
|
|
"io"
|
2014-07-28 01:41:25 -07:00
|
|
|
"net"
|
2014-07-02 16:03:04 -07:00
|
|
|
|
2015-04-01 17:30:16 -07:00
|
|
|
. "github.com/tendermint/tendermint/common"
|
2015-04-20 15:29:01 -07:00
|
|
|
"github.com/tendermint/tendermint/types"
|
2015-08-04 18:44:15 -07:00
|
|
|
"github.com/tendermint/tendermint/wire"
|
2014-06-18 20:48:32 -07:00
|
|
|
)
|
|
|
|
|
2014-06-24 17:28:40 -07:00
|
|
|
type Peer struct {
|
2015-07-19 17:42:01 -07:00
|
|
|
BaseService
|
|
|
|
|
2014-07-10 22:14:23 -07:00
|
|
|
outbound bool
|
2014-07-28 01:41:25 -07:00
|
|
|
mconn *MConnection
|
2014-07-29 23:53:35 -07:00
|
|
|
|
2015-04-20 15:29:01 -07:00
|
|
|
*types.NodeInfo
|
2014-09-14 15:37:32 -07:00
|
|
|
Key string
|
|
|
|
Data *CMap // User data.
|
2014-06-18 20:48:32 -07:00
|
|
|
}
|
|
|
|
|
2015-07-13 13:17:47 -07:00
|
|
|
// NOTE: blocking
|
2015-07-14 17:52:54 -07:00
|
|
|
// Before creating a peer with newPeer(), perform a handshake on connection.
|
2015-04-20 15:29:01 -07:00
|
|
|
func peerHandshake(conn net.Conn, ourNodeInfo *types.NodeInfo) (*types.NodeInfo, error) {
|
|
|
|
var peerNodeInfo = new(types.NodeInfo)
|
|
|
|
var err1 error
|
|
|
|
var err2 error
|
2015-07-15 12:13:10 -07:00
|
|
|
Parallel(
|
|
|
|
func() {
|
|
|
|
var n int64
|
2015-07-25 15:45:45 -07:00
|
|
|
wire.WriteBinary(ourNodeInfo, conn, &n, &err1)
|
2015-07-15 12:13:10 -07:00
|
|
|
},
|
|
|
|
func() {
|
|
|
|
var n int64
|
2015-07-25 15:45:45 -07:00
|
|
|
wire.ReadBinary(peerNodeInfo, conn, &n, &err2)
|
2015-07-19 21:49:13 +00:00
|
|
|
log.Notice("Peer handshake", "peerNodeInfo", peerNodeInfo)
|
2015-07-15 12:13:10 -07:00
|
|
|
})
|
2015-04-20 15:29:01 -07:00
|
|
|
if err1 != nil {
|
|
|
|
return nil, err1
|
|
|
|
}
|
|
|
|
if err2 != nil {
|
|
|
|
return nil, err2
|
|
|
|
}
|
|
|
|
return peerNodeInfo, nil
|
|
|
|
}
|
|
|
|
|
2015-07-14 17:52:54 -07:00
|
|
|
// NOTE: call peerHandshake on conn before calling newPeer().
|
2015-04-20 15:29:01 -07:00
|
|
|
func newPeer(conn net.Conn, peerNodeInfo *types.NodeInfo, outbound bool, reactorsByCh map[byte]Reactor, chDescs []*ChannelDescriptor, onPeerError func(*Peer, interface{})) *Peer {
|
2014-07-28 01:41:25 -07:00
|
|
|
var p *Peer
|
2015-08-18 10:51:55 -07:00
|
|
|
onReceive := func(chID byte, msgBytes []byte) {
|
|
|
|
reactor := reactorsByCh[chID]
|
2014-09-14 15:37:32 -07:00
|
|
|
if reactor == nil {
|
2015-08-18 10:51:55 -07:00
|
|
|
PanicSanity(Fmt("Unknown channel %X", chID))
|
2014-09-14 15:37:32 -07:00
|
|
|
}
|
2015-08-18 10:51:55 -07:00
|
|
|
reactor.Receive(chID, p, msgBytes)
|
2014-09-14 15:37:32 -07:00
|
|
|
}
|
2014-07-28 01:41:25 -07:00
|
|
|
onError := func(r interface{}) {
|
2015-07-20 14:40:41 -07:00
|
|
|
p.Stop()
|
2014-07-28 01:41:25 -07:00
|
|
|
onPeerError(p, r)
|
|
|
|
}
|
2014-09-14 15:37:32 -07:00
|
|
|
mconn := NewMConnection(conn, chDescs, onReceive, onError)
|
2014-07-28 01:41:25 -07:00
|
|
|
p = &Peer{
|
|
|
|
outbound: outbound,
|
|
|
|
mconn: mconn,
|
2015-04-20 15:29:01 -07:00
|
|
|
NodeInfo: peerNodeInfo,
|
2015-07-15 14:31:03 -07:00
|
|
|
Key: peerNodeInfo.PubKey.KeyString(),
|
2014-09-14 15:37:32 -07:00
|
|
|
Data: NewCMap(),
|
2014-07-01 14:50:24 -07:00
|
|
|
}
|
2015-07-20 14:40:41 -07:00
|
|
|
p.BaseService = *NewBaseService(log, "Peer", p)
|
2014-07-28 01:41:25 -07:00
|
|
|
return p
|
2014-06-28 13:09:04 -07:00
|
|
|
}
|
|
|
|
|
2015-08-04 18:44:15 -07:00
|
|
|
func (p *Peer) OnStart() error {
|
2015-07-21 18:31:01 -07:00
|
|
|
p.BaseService.OnStart()
|
2015-08-04 18:44:15 -07:00
|
|
|
_, err := p.mconn.Start()
|
|
|
|
return err
|
2014-06-18 20:48:32 -07:00
|
|
|
}
|
|
|
|
|
2015-07-21 18:31:01 -07:00
|
|
|
func (p *Peer) OnStop() {
|
|
|
|
p.BaseService.OnStop()
|
2015-07-19 17:42:01 -07:00
|
|
|
p.mconn.Stop()
|
2014-09-14 15:37:32 -07:00
|
|
|
}
|
|
|
|
|
2014-12-29 15:14:54 -08:00
|
|
|
func (p *Peer) Connection() *MConnection {
|
|
|
|
return p.mconn
|
2014-09-14 15:37:32 -07:00
|
|
|
}
|
|
|
|
|
2014-07-10 22:14:23 -07:00
|
|
|
func (p *Peer) IsOutbound() bool {
|
|
|
|
return p.outbound
|
2014-07-09 18:33:44 -07:00
|
|
|
}
|
|
|
|
|
2015-08-18 10:51:55 -07:00
|
|
|
func (p *Peer) Send(chID byte, msg interface{}) bool {
|
2015-07-19 17:42:01 -07:00
|
|
|
if !p.IsRunning() {
|
2014-08-03 15:50:28 -07:00
|
|
|
return false
|
|
|
|
}
|
2015-08-18 10:51:55 -07:00
|
|
|
return p.mconn.Send(chID, msg)
|
2014-08-03 15:50:28 -07:00
|
|
|
}
|
|
|
|
|
2015-08-18 10:51:55 -07:00
|
|
|
func (p *Peer) TrySend(chID byte, msg interface{}) bool {
|
2015-07-19 17:42:01 -07:00
|
|
|
if !p.IsRunning() {
|
2014-07-01 14:50:24 -07:00
|
|
|
return false
|
|
|
|
}
|
2015-08-18 10:51:55 -07:00
|
|
|
return p.mconn.TrySend(chID, msg)
|
2014-06-18 20:48:32 -07:00
|
|
|
}
|
|
|
|
|
2015-08-18 10:51:55 -07:00
|
|
|
func (p *Peer) CanSend(chID byte) bool {
|
2015-07-19 17:42:01 -07:00
|
|
|
if !p.IsRunning() {
|
2014-08-10 16:35:08 -07:00
|
|
|
return false
|
2014-07-14 14:04:26 -07:00
|
|
|
}
|
2015-08-18 10:51:55 -07:00
|
|
|
return p.mconn.CanSend(chID)
|
2014-07-14 14:04:26 -07:00
|
|
|
}
|
|
|
|
|
2014-06-24 17:28:40 -07:00
|
|
|
func (p *Peer) WriteTo(w io.Writer) (n int64, err error) {
|
2015-07-25 15:45:45 -07:00
|
|
|
wire.WriteString(p.Key, w, &n, &err)
|
2014-09-03 20:41:57 -07:00
|
|
|
return
|
2014-06-18 20:48:32 -07:00
|
|
|
}
|
|
|
|
|
2014-06-29 00:35:16 -07:00
|
|
|
func (p *Peer) String() string {
|
2014-07-17 00:54:48 -07:00
|
|
|
if p.outbound {
|
2015-09-11 18:17:19 -07:00
|
|
|
return fmt.Sprintf("Peer{%v %v out}", p.mconn, p.Key[:12])
|
2014-07-17 00:54:48 -07:00
|
|
|
} else {
|
2015-09-11 18:17:19 -07:00
|
|
|
return fmt.Sprintf("Peer{%v %v in}", p.mconn, p.Key[:12])
|
2014-07-01 14:50:24 -07:00
|
|
|
}
|
2014-06-18 20:48:32 -07:00
|
|
|
}
|
2014-07-29 23:53:35 -07:00
|
|
|
|
|
|
|
func (p *Peer) Equals(other *Peer) bool {
|
2014-08-03 15:50:28 -07:00
|
|
|
return p.Key == other.Key
|
2014-07-29 23:53:35 -07:00
|
|
|
}
|