|
|
- package peer
-
- import (
- . "github.com/tendermint/tendermint/binary"
- "sync/atomic"
- "sync"
- "io"
- "time"
- )
-
- /* Peer */
-
- type Peer struct {
- outgoing bool
- conn *Connection
- channels map[String]*Channel
-
- mtx sync.Mutex
- quit chan struct{}
- stopped uint32
- }
-
- func (p *Peer) Start(peerInQueues map[String]chan *InboundMsg ) {
- for chName, _ := range p.channels {
- go p.inHandler(chName, peerInQueues[chName])
- go p.outHandler(chName)
- }
- }
-
- func (p *Peer) Stop() {
- // lock
- p.mtx.Lock()
- if atomic.CompareAndSwapUint32(&p.stopped, 0, 1) {
- close(p.quit)
- p.conn.Stop()
- }
- p.mtx.Unlock()
- // unlock
- }
-
- func (p *Peer) LocalAddress() *NetAddress {
- return p.conn.LocalAddress()
- }
-
- func (p *Peer) RemoteAddress() *NetAddress {
- return p.conn.RemoteAddress()
- }
-
- func (p *Peer) Channel(chName String) *Channel {
- return p.channels[chName]
- }
-
- // Queue the msg for output.
- // If the queue is full, just return false.
- func (p *Peer) TryQueueOut(chName String, msg Msg) bool {
- channel := p.Channel(chName)
- outQueue := channel.OutQueue()
-
- // 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
- }
- // unlock deferred
- }
-
- func (p *Peer) WriteTo(w io.Writer) (n int64, err error) {
- return p.RemoteAddress().WriteTo(w)
- }
-
- func (p *Peer) inHandler(chName String, inboundMsgQueue chan<- *InboundMsg) {
- channel := p.channels[chName]
- inQueue := channel.InQueue()
-
- FOR_LOOP:
- for {
- select {
- case <-p.quit:
- break FOR_LOOP
- case msg := <-inQueue:
- // send to inboundMsgQueue
- inboundMsg := &InboundMsg{
- Peer: p,
- Channel: channel,
- Time: Time{time.Now()},
- Msg: msg,
- }
- select {
- case <-p.quit:
- break FOR_LOOP
- case inboundMsgQueue <- inboundMsg:
- continue
- }
- }
- }
-
- // cleanup
- // (none)
- }
-
- func (p *Peer) outHandler(chName String) {
- outQueue := p.channels[chName].outQueue
- FOR_LOOP:
- for {
- select {
- case <-p.quit:
- 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)
- }
- }
-
- // cleanup
- // (none)
- }
-
-
- /* Channel */
-
- type Channel struct {
- name String
- inQueue chan Msg
- outQueue chan Msg
- //stats Stats
- }
-
- func NewChannel(name string, bufferSize int) *Channel {
- return &Channel{
- name: String(name),
- inQueue: make(chan Msg, bufferSize),
- outQueue: make(chan Msg, buffersize),
- }
- }
-
- func (c *Channel) Name() String {
- return c.name
- }
-
- func (c *Channel) InQueue() <-chan Msg {
- return c.inQueue
- }
-
- func (c *Channel) OutQueue() chan<- Msg {
- return c.outQueue
- }
|