You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

3.2 KiB

ADR 012: PeerTransport

Context

One of the more apparent problems with the current architecture in the p2p package is that there is no clear separation of concerns between different components. Most notably the Switch is currently doing physical connection handling. An artifact is the dependency of the Switch on [config.P2PConfig](05a76fb517/config/config.go (L272-L339)).

Addresses:

First iteraton in #2067

Decision

Transport concerns will be handled by a new component (PeerTransport) which will provide Peers at its boundary to the caller. In turn Switch will use this new component accept new Peers and dial them based on NetAddress.

PeerTransport

Responsible for emitting and connecting to Peers. The implementation of Peer is left to the transport, which implies that the chosen transport dictates the characteristics of the implementation handed back to the Switch. Each transport implementation is responsible to filter establishing peers specific to its domain, for the default multiplexed implementation the following will apply:

  • connections from our own node
  • handshake fails
  • upgrade to secret connection fails
  • prevent duplicate ip
  • prevent duplicate id
  • nodeinfo incompatibility
// PeerTransport proxies incoming and outgoing peer connections.
type PeerTransport interface {
	// Accept returns a newly connected Peer.
	Accept() (Peer, error)

	// Dial connects to a Peer.
	Dial(NetAddress) (Peer, error)
}

// EXAMPLE OF DEFAULT IMPLEMENTATION

// multiplexTransport accepts tcp connections and upgrades to multiplexted
// peers.
type multiplexTransport struct {
	listener net.Listener

	acceptc chan accept
	closec  <-chan struct{}
	listenc <-chan struct{}

	dialTimeout      time.Duration
	handshakeTimeout time.Duration
	nodeAddr         NetAddress
	nodeInfo         NodeInfo
	nodeKey          NodeKey

	// TODO(xla): Remove when MConnection is refactored into mPeer.
	mConfig conn.MConnConfig
}

var _ PeerTransport = (*multiplexTransport)(nil)

// NewMTransport returns network connected multiplexed peers.
func NewMTransport(
	nodeAddr NetAddress,
	nodeInfo NodeInfo,
	nodeKey NodeKey,
) *multiplexTransport

Switch

From now the Switch will depend on a fully setup PeerTransport to retrieve/reach out to its peers. As the more low-level concerns are pushed to the transport, we can omit passing the config.P2PConfig to the Switch.

func NewSwitch(transport PeerTransport, opts ...SwitchOption) *Switch

Status

In Review.

Consequences

Positive

  • free Switch from transport concerns - simpler implementation
  • pluggable transport implementation - simpler test setup
  • remove Switch dependency on P2PConfig - easier to test

Negative

  • more setup for tests which depend on Switches

Neutral

  • multiplexed will be the default implementation

[0] These guards could be potentially extended to be pluggable much like middlewares to express different concerns required by differentally configured environments.