- # 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`](https://github.com/tendermint/tendermint/blob/05a76fb517f50da27b4bfcdc7b4cf185fc61eff6/config/config.go#L272-L339).
-
- Addresses:
-
- - [#2046](https://github.com/tendermint/tendermint/issues/2046)
- - [#2047](https://github.com/tendermint/tendermint/issues/2047)
-
- First iteraton in [#2067](https://github.com/tendermint/tendermint/issues/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 `Peer`s 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
-
- ```go
- // 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.
-
- ```go
- 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.
|