package peer import ( . "github.com/tendermint/tendermint/binary" "github.com/tendermint/tendermint/merkle" "sync" "io" ) /* Client */ type Client struct { listener *Listener addrBook AddrBook strategies map[String]*FilterStrategy targetNumPeers int peersMtx sync.Mutex peers merkle.Tree // addr -> *Peer filtersMtx sync.Mutex filters merkle.Tree // channelName -> Filter (objects that I know of) } func NewClient(protocol string, laddr string) *Client { // XXX set the handler listener := NewListener(protocol, laddr, nil) c := &Client{ listener: listener, peers: merkle.NewIAVLTree(nil), filters: merkle.NewIAVLTree(nil), } return c } func (c *Client) Start() (<-chan *IncomingMsg) { return nil } func (c *Client) Stop() { c.listener.Close() } func (c *Client) LocalAddress() *NetAddress { return c.listener.LocalAddress() } func (c *Client) ConnectTo(addr *NetAddress) (*Peer, error) { conn, err := addr.Dial() if err != nil { return nil, err } peer := NewPeer(conn) // lock c.peersMtx.Lock() c.peers.Put(addr, peer) c.peersMtx.Unlock() // unlock return peer, nil } func (c *Client) Broadcast(channel String, msg Binary) { for v := range c.peersCopy().Values() { peer, ok := v.(*Peer) if !ok { panic("Expected peer but got something else") } peer.Queue(channel, msg) } } // Updates the client's filter for a channel & broadcasts it. func (c *Client) UpdateFilter(channel String, filter Filter) { c.filtersMtx.Lock() c.filters.Put(channel, filter) c.filtersMtx.Unlock() c.Broadcast("", &NewFilterMsg{ Channel: channel, Filter: filter, }) } func (c *Client) peersCopy() merkle.Tree { c.peersMtx.Lock(); defer c.peersMtx.Unlock() return c.peers.Copy() } /* Channel */ type Channel struct { Name String Filter Filter //Stats Stats } /* Peer */ type Peer struct { Conn *Connection Channels map[String]*Channel } func NewPeer(conn *Connection) *Peer { return &Peer{ Conn: conn, Channels: nil, } } // Must be quick and nonblocking. func (p *Peer) Queue(channel String, msg Binary) {} func (p *Peer) WriteTo(w io.Writer) (n int64, err error) { return 0, nil // TODO } /* IncomingMsg */ type IncomingMsg struct { SPeer *Peer SChan *Channel Time Time Msg Binary } /* Filter A Filter could be a bloom filter for lossy filtering, or could be a lossless filter. Either way, it's used to keep track of what a peer knows of. */ type Filter interface { Binary Add(ByteSlice) Has(ByteSlice) bool } /* FilterStrategy Defines how filters are generated per peer, and whether they need to get refreshed occasionally. */ type FilterStrategy interface { LoadFilter(ByteSlice) Filter } /* NewFilterMsg */ type NewFilterMsg struct { Channel String Filter Filter } func (m *NewFilterMsg) WriteTo(w io.Writer) (int64, error) { return 0, nil // TODO }