- package p2p
-
- import (
- "context"
- "errors"
- "fmt"
- "net"
- "net/url"
-
- "github.com/tendermint/tendermint/crypto"
- "github.com/tendermint/tendermint/p2p/conn"
- )
-
- // Transport is an arbitrary mechanism for exchanging bytes with a peer.
- type Transport interface {
- // Accept waits for the next inbound connection on a listening endpoint.
- Accept(context.Context) (Connection, error)
-
- // Dial creates an outbound connection to an endpoint.
- Dial(context.Context, Endpoint) (Connection, error)
-
- // Endpoints lists endpoints the transport is listening on. Any endpoint IP
- // addresses do not need to be normalized in any way (e.g. 0.0.0.0 is
- // valid), as they should be preprocessed before being advertised.
- Endpoints() []Endpoint
-
- // Close stops accepting new connections, but does not close active connections.
- Close() error
-
- // SetChannelDescriptors sets the channel descriptors for the transport.
- // FIXME: This is only here for compatibility with the current Switch code.
- SetChannelDescriptors(chDescs []*conn.ChannelDescriptor)
- }
-
- // Protocol identifies a transport protocol.
- type Protocol string
-
- // Endpoint represents a transport connection endpoint, either local or remote.
- type Endpoint struct {
- // PeerID specifies the peer ID of the endpoint.
- //
- // FIXME: This is here for backwards-compatibility with the existing MConn
- // protocol, we should consider moving this higher in the stack (i.e. to
- // the router).
- PeerID ID
-
- // Protocol specifies the transport protocol, used by the router to pick a
- // transport for an endpoint.
- Protocol Protocol
-
- // Path is an optional, arbitrary transport-specific path or identifier.
- Path string
-
- // IP is an IP address (v4 or v6) to connect to. If set, this defines the
- // endpoint as a networked endpoint.
- IP net.IP
-
- // Port is a network port (either TCP or UDP). If not set, a default port
- // may be used depending on the protocol.
- Port uint16
- }
-
- // String formats an endpoint as a URL string.
- func (e Endpoint) String() string {
- u := url.URL{Scheme: string(e.Protocol)}
- if e.PeerID != "" {
- u.User = url.User(string(e.PeerID))
- }
- if len(e.IP) > 0 {
- u.Host = e.IP.String()
- if e.Port > 0 {
- u.Host += fmt.Sprintf(":%v", e.Port)
- }
- } else if e.Path != "" {
- u.Opaque = e.Path
- }
- return u.String()
- }
-
- // Validate validates an endpoint.
- func (e Endpoint) Validate() error {
- switch {
- case e.PeerID == "":
- return errors.New("endpoint has no peer ID")
- case e.Protocol == "":
- return errors.New("endpoint has no protocol")
- case len(e.IP) == 0 && len(e.Path) == 0:
- return errors.New("endpoint must have either IP or path")
- case e.Port > 0 && len(e.IP) == 0:
- return fmt.Errorf("endpoint has port %v but no IP", e.Port)
- default:
- return nil
- }
- }
-
- // NetAddress returns a NetAddress for the endpoint.
- // FIXME: This is temporary for compatibility with the old P2P stack.
- func (e Endpoint) NetAddress() *NetAddress {
- return &NetAddress{
- ID: e.PeerID,
- IP: e.IP,
- Port: e.Port,
- }
- }
-
- // Connection represents an established connection between two endpoints.
- //
- // FIXME: This is a temporary interface while we figure out whether we'll be
- // adopting QUIC or not. If we do, this should be a byte-oriented multi-stream
- // interface with one goroutine consuming each stream, and the MConnection
- // transport either needs protocol changes or a shim. For details, see:
- // https://github.com/tendermint/spec/pull/227
- //
- // FIXME: The interface is currently very broad in order to accommodate
- // MConnection behavior that the rest of the P2P stack relies on. This should be
- // removed once the P2P core is rewritten.
- type Connection interface {
- // ReceiveMessage returns the next message received on the connection,
- // blocking until one is available. io.EOF is returned when closed.
- ReceiveMessage() (chID byte, msg []byte, err error)
-
- // SendMessage sends a message on the connection.
- // FIXME: For compatibility with the current Peer, it returns an additional
- // boolean false if the message timed out waiting to be accepted into the
- // send buffer.
- SendMessage(chID byte, msg []byte) (bool, error)
-
- // TrySendMessage is a non-blocking version of SendMessage that returns
- // immediately if the message buffer is full. It returns true if the message
- // was accepted.
- //
- // FIXME: This is here for backwards-compatibility with the current Peer
- // code, and should be removed when possible.
- TrySendMessage(chID byte, msg []byte) (bool, error)
-
- // LocalEndpoint returns the local endpoint for the connection.
- LocalEndpoint() Endpoint
-
- // RemoteEndpoint returns the remote endpoint for the connection.
- RemoteEndpoint() Endpoint
-
- // PubKey returns the remote peer's public key.
- PubKey() crypto.PubKey
-
- // NodeInfo returns the remote peer's node info.
- NodeInfo() NodeInfo
-
- // Close closes the connection.
- Close() error
-
- // FlushClose flushes all pending sends and then closes the connection.
- //
- // FIXME: This only exists for backwards-compatibility with the current
- // MConnection implementation. There should really be a separate Flush()
- // method, but there is no easy way to synchronously flush pending data with
- // the current MConnection structure.
- FlushClose() error
-
- // Status returns the current connection status.
- // FIXME: Only here for compatibility with the current Peer code.
- Status() conn.ConnectionStatus
- }
|