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-01 14:50:24 -07:00
|
|
|
"sync/atomic"
|
2014-07-02 16:03:04 -07:00
|
|
|
|
|
|
|
. "github.com/tendermint/tendermint/binary"
|
2014-06-18 20:48:32 -07:00
|
|
|
)
|
|
|
|
|
2014-06-24 17:28:40 -07:00
|
|
|
/* Peer */
|
2014-06-18 20:48:32 -07:00
|
|
|
|
2014-06-24 17:28:40 -07:00
|
|
|
type Peer struct {
|
2014-07-10 22:14:23 -07:00
|
|
|
outbound bool
|
2014-07-28 01:41:25 -07:00
|
|
|
mconn *MConnection
|
2014-07-04 14:29:27 -07:00
|
|
|
started uint32
|
|
|
|
stopped uint32
|
2014-07-29 23:53:35 -07:00
|
|
|
|
|
|
|
Key string
|
2014-06-18 20:48:32 -07:00
|
|
|
}
|
|
|
|
|
2014-07-28 01:41:25 -07:00
|
|
|
func newPeer(conn net.Conn, outbound bool, chDescs []*ChannelDescriptor, onPeerError func(*Peer, interface{})) *Peer {
|
|
|
|
var p *Peer
|
|
|
|
onError := func(r interface{}) {
|
|
|
|
p.stop()
|
|
|
|
onPeerError(p, r)
|
|
|
|
}
|
|
|
|
mconn := NewMConnection(conn, chDescs, onError)
|
|
|
|
p = &Peer{
|
|
|
|
outbound: outbound,
|
|
|
|
mconn: mconn,
|
2014-07-04 14:29:27 -07:00
|
|
|
stopped: 0,
|
2014-07-29 23:53:35 -07:00
|
|
|
Key: mconn.RemoteAddress.String(),
|
2014-07-01 14:50:24 -07:00
|
|
|
}
|
2014-07-29 23:53:35 -07:00
|
|
|
mconn.Peer = p // hacky optimization
|
2014-07-28 01:41:25 -07:00
|
|
|
return p
|
2014-06-28 13:09:04 -07:00
|
|
|
}
|
|
|
|
|
2014-07-28 01:41:25 -07:00
|
|
|
func (p *Peer) start() {
|
2014-07-04 14:29:27 -07:00
|
|
|
if atomic.CompareAndSwapUint32(&p.started, 0, 1) {
|
2014-07-28 01:41:25 -07:00
|
|
|
log.Debug("Starting %v", p)
|
|
|
|
p.mconn.Start()
|
2014-07-01 14:50:24 -07:00
|
|
|
}
|
2014-06-18 20:48:32 -07:00
|
|
|
}
|
|
|
|
|
2014-07-04 14:29:27 -07:00
|
|
|
func (p *Peer) stop() {
|
2014-07-01 14:50:24 -07:00
|
|
|
if atomic.CompareAndSwapUint32(&p.stopped, 0, 1) {
|
2014-07-14 16:15:13 -07:00
|
|
|
log.Debug("Stopping %v", p)
|
2014-07-28 01:41:25 -07:00
|
|
|
p.mconn.Stop()
|
2014-07-01 14:50:24 -07:00
|
|
|
}
|
2014-06-18 20:48: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
|
|
|
}
|
|
|
|
|
2014-07-28 01:41:25 -07:00
|
|
|
func (p *Peer) TrySend(chId byte, bytes ByteSlice) bool {
|
2014-07-04 14:29:27 -07:00
|
|
|
if atomic.LoadUint32(&p.stopped) == 1 {
|
2014-07-01 14:50:24 -07:00
|
|
|
return false
|
|
|
|
}
|
2014-07-28 01:41:25 -07:00
|
|
|
return p.mconn.TrySend(chId, bytes)
|
2014-06-18 20:48:32 -07:00
|
|
|
}
|
|
|
|
|
2014-07-28 01:41:25 -07:00
|
|
|
func (p *Peer) Send(chId byte, bytes ByteSlice) bool {
|
2014-07-14 14:04:26 -07:00
|
|
|
if atomic.LoadUint32(&p.stopped) == 1 {
|
|
|
|
return false
|
|
|
|
}
|
2014-07-28 01:41:25 -07:00
|
|
|
return p.mconn.Send(chId, bytes)
|
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) {
|
2014-07-29 23:53:35 -07:00
|
|
|
return p.mconn.RemoteAddress.WriteTo(w)
|
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 {
|
2014-07-28 01:41:25 -07:00
|
|
|
return fmt.Sprintf("P(->%v)", p.mconn)
|
2014-07-17 00:54:48 -07:00
|
|
|
} else {
|
2014-07-28 01:41:25 -07:00
|
|
|
return fmt.Sprintf("P(%v->)", p.mconn)
|
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 {
|
|
|
|
return p.mconn.RemoteAddress.Equals(other.mconn.RemoteAddress)
|
|
|
|
}
|