tendermint/peer/peer.go

160 lines
3.3 KiB
Go
Raw Normal View History

2014-06-18 20:48:32 -07:00
package peer
import (
2014-06-25 21:37:20 -07:00
. "github.com/tendermint/tendermint/binary"
"sync/atomic"
2014-06-18 20:48:32 -07:00
"sync"
2014-06-25 21:37:20 -07:00
"io"
"time"
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 {
outgoing bool
conn *Connection
channels map[String]*Channel
2014-06-18 20:48:32 -07:00
2014-06-24 17:28:40 -07:00
mtx sync.Mutex
quit chan struct{}
stopped uint32
2014-06-18 20:48:32 -07:00
}
2014-06-28 13:09:04 -07:00
func NewPeer(conn *Connection) *Peer {
return &Peer{
conn: conn,
quit: make(chan struct{}),
stopped: 0,
}
}
2014-06-24 17:28:40 -07:00
func (p *Peer) Start(peerInQueues map[String]chan *InboundMsg ) {
for chName, _ := range p.channels {
go p.inHandler(chName, peerInQueues[chName])
go p.outHandler(chName)
2014-06-18 20:48:32 -07:00
}
}
2014-06-24 17:28:40 -07:00
func (p *Peer) Stop() {
// lock
p.mtx.Lock()
if atomic.CompareAndSwapUint32(&p.stopped, 0, 1) {
close(p.quit)
p.conn.Stop()
2014-06-18 20:48:32 -07:00
}
2014-06-24 17:28:40 -07:00
p.mtx.Unlock()
// unlock
2014-06-18 20:48:32 -07:00
}
2014-06-24 17:28:40 -07:00
func (p *Peer) LocalAddress() *NetAddress {
return p.conn.LocalAddress()
2014-06-18 20:48:32 -07:00
}
2014-06-24 17:28:40 -07:00
func (p *Peer) RemoteAddress() *NetAddress {
return p.conn.RemoteAddress()
2014-06-18 20:48:32 -07:00
}
2014-06-24 17:28:40 -07:00
func (p *Peer) Channel(chName String) *Channel {
return p.channels[chName]
2014-06-18 20:48:32 -07:00
}
// Queue the msg for output.
2014-06-24 17:28:40 -07:00
// If the queue is full, just return false.
func (p *Peer) TryQueueOut(chName String, msg Msg) bool {
channel := p.Channel(chName)
outQueue := channel.OutQueue()
2014-06-18 20:48:32 -07:00
2014-06-24 17:28:40 -07:00
// lock & defer
p.mtx.Lock(); defer p.mtx.Unlock()
if p.stopped == 1 { return false }
select {
case outQueue <- msg:
return true
default: // buffer full
return false
2014-06-18 20:48:32 -07:00
}
2014-06-24 17:28:40 -07:00
// unlock deferred
2014-06-18 20:48:32 -07:00
}
2014-06-24 17:28:40 -07:00
func (p *Peer) WriteTo(w io.Writer) (n int64, err error) {
return p.RemoteAddress().WriteTo(w)
2014-06-18 20:48:32 -07:00
}
2014-06-24 17:28:40 -07:00
func (p *Peer) inHandler(chName String, inboundMsgQueue chan<- *InboundMsg) {
channel := p.channels[chName]
inQueue := channel.InQueue()
2014-06-18 20:48:32 -07:00
2014-06-24 17:28:40 -07:00
FOR_LOOP:
for {
select {
2014-06-25 21:37:20 -07:00
case <-p.quit:
2014-06-24 17:28:40 -07:00
break FOR_LOOP
case msg := <-inQueue:
// send to inboundMsgQueue
inboundMsg := &InboundMsg{
Peer: p,
Channel: channel,
2014-06-25 21:37:20 -07:00
Time: Time{time.Now()},
2014-06-24 17:28:40 -07:00
Msg: msg,
2014-06-18 20:48:32 -07:00
}
2014-06-24 17:28:40 -07:00
select {
2014-06-25 21:37:20 -07:00
case <-p.quit:
2014-06-24 17:28:40 -07:00
break FOR_LOOP
case inboundMsgQueue <- inboundMsg:
2014-06-18 20:48:32 -07:00
continue
}
}
}
2014-06-24 17:28:40 -07:00
// cleanup
// (none)
2014-06-18 20:48:32 -07:00
}
2014-06-24 17:28:40 -07:00
func (p *Peer) outHandler(chName String) {
2014-06-25 21:37:20 -07:00
outQueue := p.channels[chName].outQueue
2014-06-24 17:28:40 -07:00
FOR_LOOP:
2014-06-18 20:48:32 -07:00
for {
select {
2014-06-25 21:37:20 -07:00
case <-p.quit:
2014-06-24 17:28:40 -07:00
break FOR_LOOP
case msg := <-outQueue:
// blocks until the connection is Stop'd,
// which happens when this peer is Stop'd.
p.conn.QueueOut(msg.Bytes)
2014-06-18 20:48:32 -07:00
}
}
2014-06-24 17:28:40 -07:00
// cleanup
// (none)
2014-06-18 20:48:32 -07:00
}
2014-06-24 17:28:40 -07:00
/* Channel */
2014-06-18 20:48:32 -07:00
2014-06-24 17:28:40 -07:00
type Channel struct {
name String
inQueue chan Msg
outQueue chan Msg
//stats Stats
}
2014-06-18 20:48:32 -07:00
func NewChannel(name string, bufferSize int) *Channel {
2014-06-24 17:28:40 -07:00
return &Channel{
name: String(name),
inQueue: make(chan Msg, bufferSize),
2014-06-28 13:09:04 -07:00
outQueue: make(chan Msg, bufferSize),
2014-06-18 20:48:32 -07:00
}
}
2014-06-25 21:37:20 -07:00
func (c *Channel) Name() String {
return c.name
}
2014-06-24 17:28:40 -07:00
func (c *Channel) InQueue() <-chan Msg {
return c.inQueue
2014-06-18 20:48:32 -07:00
}
2014-06-24 17:28:40 -07:00
func (c *Channel) OutQueue() chan<- Msg {
return c.outQueue
2014-06-18 20:48:32 -07:00
}