|
|
- package p2p
-
- import (
- "sync"
-
- "github.com/gogo/protobuf/proto"
- )
-
- // ChannelID is an arbitrary channel ID.
- type ChannelID uint16
-
- // Envelope specifies the message receiver and sender.
- type Envelope struct {
- From NodeID // Message sender, or empty for outbound messages.
- To NodeID // Message receiver, or empty for inbound messages.
- Broadcast bool // Send message to all connected peers, ignoring To.
- Message proto.Message // Payload.
-
- // For internal use in the Router.
- channelID ChannelID
- }
-
- // Strip strips internal information from the envelope. Primarily used for
- // testing, such that returned envelopes can be compared with literals.
- func (e Envelope) Strip() Envelope {
- e.channelID = 0
- return e
- }
-
- // Channel is a bidirectional channel for Protobuf message exchange with peers.
- // A Channel is safe for concurrent use by multiple goroutines.
- type Channel struct {
- closeOnce sync.Once
-
- // id defines the unique channel ID.
- id ChannelID
-
- // messageType specifies the type of messages exchanged via the channel, and
- // is used e.g. for automatic unmarshaling.
- messageType proto.Message
-
- // inCh is a channel for receiving inbound messages. Envelope.From is always
- // set.
- inCh chan Envelope
-
- // outCh is a channel for sending outbound messages. Envelope.To or Broadcast
- // must be set, otherwise the message is discarded.
- outCh chan Envelope
-
- // errCh is a channel for reporting peer errors to the router, typically used
- // when peers send an invalid or malignant message.
- errCh chan PeerError
-
- // doneCh is used to signal that a Channel is closed. A Channel is bi-directional
- // and should be closed by the reactor, where as the router is responsible
- // for explicitly closing the internal In channel.
- doneCh chan struct{}
- }
-
- // NewChannel returns a reference to a new p2p Channel. It is the reactor's
- // responsibility to close the Channel. After a channel is closed, the router may
- // safely and explicitly close the internal In channel.
- func NewChannel(id ChannelID, mType proto.Message, in, out chan Envelope, errCh chan PeerError) *Channel {
- return &Channel{
- id: id,
- messageType: mType,
- inCh: in,
- outCh: out,
- errCh: errCh,
- doneCh: make(chan struct{}),
- }
- }
-
- // ID returns the Channel's ID.
- func (c *Channel) ID() ChannelID {
- return c.id
- }
-
- // In returns a read-only inbound go channel. This go channel should be used by
- // reactors to consume Envelopes sent from peers.
- func (c *Channel) In() <-chan Envelope {
- return c.inCh
- }
-
- // Out returns a write-only outbound go channel. This go channel should be used
- // by reactors to route Envelopes to other peers.
- func (c *Channel) Out() chan<- Envelope {
- return c.outCh
- }
-
- // Error returns a write-only outbound go channel designated for peer errors only.
- // This go channel should be used by reactors to send peer errors when consuming
- // Envelopes sent from other peers.
- func (c *Channel) Error() chan<- PeerError {
- return c.errCh
- }
-
- // Close closes the outbound channel and marks the Channel as done. Internally,
- // the outbound outCh and peer error errCh channels are closed. It is the reactor's
- // responsibility to invoke Close. Any send on the Out or Error channel will
- // panic after the Channel is closed.
- //
- // NOTE: After a Channel is closed, the router may safely assume it can no longer
- // send on the internal inCh, however it should NEVER explicitly close it as
- // that could result in panics by sending on a closed channel.
- func (c *Channel) Close() {
- c.closeOnce.Do(func() {
- close(c.doneCh)
- close(c.outCh)
- close(c.errCh)
- })
- }
-
- // Done returns the Channel's internal channel that should be used by a router
- // to signal when it is safe to send on the internal inCh go channel.
- func (c *Channel) Done() <-chan struct{} {
- return c.doneCh
- }
-
- // Wrapper is a Protobuf message that can contain a variety of inner messages.
- // If a Channel's message type implements Wrapper, the channel will
- // automatically (un)wrap passed messages using the container type, such that
- // the channel can transparently support multiple message types.
- type Wrapper interface {
- // Wrap will take a message and wrap it in this one.
- Wrap(proto.Message) error
-
- // Unwrap will unwrap the inner message contained in this message.
- Unwrap() (proto.Message, error)
- }
|