Skip to content

Commit

Permalink
RoutedHost: Embed the underlying host instead of hiding it
Browse files Browse the repository at this point in the history
When using a libp2p host with routing, the underlying concrete type is RoutedHost.
This type wraps the original Host type and hides it into a private field,
which makes it hard to make interface type assertions on the host.

E.g. sometimes it's useful to have access to the underlying instance of the IDService,
which is exposed by BasicHost as a method `IDService() identityIDService`, but is inaccessible
for type assertions because RoutedHost hides the BasicHost in its private field.

This commit uses type embedding, instead of a private field, to fix it.
  • Loading branch information
burdiyan committed Sep 19, 2024
1 parent 9038a72 commit ed10352
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 53 deletions.
67 changes: 15 additions & 52 deletions p2p/host/routed/routed.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@ import (
"fmt"
"time"

"github.com/libp2p/go-libp2p/core/connmgr"
"github.com/libp2p/go-libp2p/core/event"
"github.com/libp2p/go-libp2p/core/host"
"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/peerstore"
"github.com/libp2p/go-libp2p/core/protocol"
"github.com/libp2p/go-libp2p/core/routing"

logging "github.com/ipfs/go-log/v2"

Expand All @@ -28,15 +27,12 @@ const AddressTTL = time.Second * 10
// This allows the Host to find the addresses for peers when
// it does not have them.
type RoutedHost struct {
host host.Host // embedded other host.
route Routing
host.Host
route routing.PeerRouting
}

type Routing interface {
FindPeer(context.Context, peer.ID) (peer.AddrInfo, error)
}

func Wrap(h host.Host, r Routing) *RoutedHost {
// Wrap makes a RoutedHost from a libp2p Host and a routing system.
func Wrap(h host.Host, r routing.PeerRouting) *RoutedHost {
return &RoutedHost{h, r}
}

Expand Down Expand Up @@ -109,7 +105,7 @@ func (rh *RoutedHost) Connect(ctx context.Context, pi peer.AddrInfo) error {

// if we're here, we got some addrs. let's use our wrapped host to connect.
pi.Addrs = addrs
if cerr := rh.host.Connect(ctx, pi); cerr != nil {
if cerr := rh.Host.Connect(ctx, pi); cerr != nil {
// We couldn't connect. Let's check if we have the most
// up-to-date addresses for the given peer. If there
// are addresses we didn't know about previously, we
Expand All @@ -135,7 +131,7 @@ func (rh *RoutedHost) Connect(ctx context.Context, pi peer.AddrInfo) error {
}

pi.Addrs = newAddrs
return rh.host.Connect(ctx, pi)
return rh.Host.Connect(ctx, pi)
}
// No appropriate new address found.
// Return the original dial error.
Expand Down Expand Up @@ -163,42 +159,6 @@ func (rh *RoutedHost) findPeerAddrs(ctx context.Context, id peer.ID) ([]ma.Multi
return pi.Addrs, nil
}

func (rh *RoutedHost) ID() peer.ID {
return rh.host.ID()
}

func (rh *RoutedHost) Peerstore() peerstore.Peerstore {
return rh.host.Peerstore()
}

func (rh *RoutedHost) Addrs() []ma.Multiaddr {
return rh.host.Addrs()
}

func (rh *RoutedHost) Network() network.Network {
return rh.host.Network()
}

func (rh *RoutedHost) Mux() protocol.Switch {
return rh.host.Mux()
}

func (rh *RoutedHost) EventBus() event.Bus {
return rh.host.EventBus()
}

func (rh *RoutedHost) SetStreamHandler(pid protocol.ID, handler network.StreamHandler) {
rh.host.SetStreamHandler(pid, handler)
}

func (rh *RoutedHost) SetStreamHandlerMatch(pid protocol.ID, m func(protocol.ID) bool, handler network.StreamHandler) {
rh.host.SetStreamHandlerMatch(pid, m, handler)
}

func (rh *RoutedHost) RemoveStreamHandler(pid protocol.ID) {
rh.host.RemoveStreamHandler(pid)
}

func (rh *RoutedHost) NewStream(ctx context.Context, p peer.ID, pids ...protocol.ID) (network.Stream, error) {
// Ensure we have a connection, with peer addresses resolved by the routing system (#207)
// It is not sufficient to let the underlying host connect, it will most likely not have
Expand All @@ -211,14 +171,17 @@ func (rh *RoutedHost) NewStream(ctx context.Context, p peer.ID, pids ...protocol
}
}

return rh.host.NewStream(ctx, p, pids...)
return rh.Host.NewStream(ctx, p, pids...)
}

// Routing exposes the underlying routing system.
func (rh *RoutedHost) Routing() routing.PeerRouting {
return rh.route
}

func (rh *RoutedHost) Close() error {
// no need to close IpfsRouting. we dont own it.
return rh.host.Close()
}
func (rh *RoutedHost) ConnManager() connmgr.ConnManager {
return rh.host.ConnManager()
return rh.Host.Close()
}

var _ (host.Host) = (*RoutedHost)(nil)
3 changes: 2 additions & 1 deletion p2p/host/routed/routed_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import (
"testing"

"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/routing"
basic "github.com/libp2p/go-libp2p/p2p/host/basic"
swarmt "github.com/libp2p/go-libp2p/p2p/net/swarm/testing"

ma "github.com/multiformats/go-multiaddr"
"github.com/stretchr/testify/require"
)

var _ Routing = (*mockRouting)(nil)
var _ routing.PeerRouting = (*mockRouting)(nil)

type mockRouting struct {
callCount int
Expand Down

0 comments on commit ed10352

Please sign in to comment.