github.com/celestiaorg/celestia-node@v0.15.0-beta.1/nodebuilder/p2p/p2p.go (about)

     1  package p2p
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"reflect"
     7  
     8  	pubsub "github.com/libp2p/go-libp2p-pubsub"
     9  	libhost "github.com/libp2p/go-libp2p/core/host"
    10  	"github.com/libp2p/go-libp2p/core/metrics"
    11  	"github.com/libp2p/go-libp2p/core/network"
    12  	"github.com/libp2p/go-libp2p/core/peer"
    13  	"github.com/libp2p/go-libp2p/core/protocol"
    14  	basichost "github.com/libp2p/go-libp2p/p2p/host/basic"
    15  	rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager"
    16  	"github.com/libp2p/go-libp2p/p2p/net/conngater"
    17  )
    18  
    19  var _ Module = (*API)(nil)
    20  
    21  // Module represents all accessible methods related to the node's p2p
    22  // host / operations.
    23  //
    24  //nolint:dupl
    25  //go:generate mockgen -destination=mocks/api.go -package=mocks . Module
    26  type Module interface {
    27  	// Info returns address information about the host.
    28  	Info(context.Context) (peer.AddrInfo, error)
    29  	// Peers returns connected peers.
    30  	Peers(context.Context) ([]peer.ID, error)
    31  	// PeerInfo returns a small slice of information Peerstore has on the
    32  	// given peer.
    33  	PeerInfo(ctx context.Context, id peer.ID) (peer.AddrInfo, error)
    34  
    35  	// Connect ensures there is a connection between this host and the peer with
    36  	// given peer.
    37  	Connect(ctx context.Context, pi peer.AddrInfo) error
    38  	// ClosePeer closes the connection to a given peer.
    39  	ClosePeer(ctx context.Context, id peer.ID) error
    40  	// Connectedness returns a state signaling connection capabilities.
    41  	Connectedness(ctx context.Context, id peer.ID) (network.Connectedness, error)
    42  	// NATStatus returns the current NAT status.
    43  	NATStatus(context.Context) (network.Reachability, error)
    44  
    45  	// BlockPeer adds a peer to the set of blocked peers.
    46  	BlockPeer(ctx context.Context, p peer.ID) error
    47  	// UnblockPeer removes a peer from the set of blocked peers.
    48  	UnblockPeer(ctx context.Context, p peer.ID) error
    49  	// ListBlockedPeers returns a list of blocked peers.
    50  	ListBlockedPeers(context.Context) ([]peer.ID, error)
    51  	// Protect adds a peer to the list of peers who have a bidirectional
    52  	// peering agreement that they are protected from being trimmed, dropped
    53  	// or negatively scored.
    54  	Protect(ctx context.Context, id peer.ID, tag string) error
    55  	// Unprotect removes a peer from the list of peers who have a bidirectional
    56  	// peering agreement that they are protected from being trimmed, dropped
    57  	// or negatively scored, returning a bool representing whether the given
    58  	// peer is protected or not.
    59  	Unprotect(ctx context.Context, id peer.ID, tag string) (bool, error)
    60  	// IsProtected returns whether the given peer is protected.
    61  	IsProtected(ctx context.Context, id peer.ID, tag string) (bool, error)
    62  
    63  	// BandwidthStats returns a Stats struct with bandwidth metrics for all
    64  	// data sent/received by the local peer, regardless of protocol or remote
    65  	// peer IDs.
    66  	BandwidthStats(context.Context) (metrics.Stats, error)
    67  	// BandwidthForPeer returns a Stats struct with bandwidth metrics associated with the given peer.ID.
    68  	// The metrics returned include all traffic sent / received for the peer, regardless of protocol.
    69  	BandwidthForPeer(ctx context.Context, id peer.ID) (metrics.Stats, error)
    70  	// BandwidthForProtocol returns a Stats struct with bandwidth metrics associated with the given
    71  	// protocol.ID.
    72  	BandwidthForProtocol(ctx context.Context, proto protocol.ID) (metrics.Stats, error)
    73  
    74  	// ResourceState returns the state of the resource manager.
    75  	ResourceState(context.Context) (rcmgr.ResourceManagerStat, error)
    76  
    77  	// PubSubPeers returns the peer IDs of the peers joined on
    78  	// the given topic.
    79  	PubSubPeers(ctx context.Context, topic string) ([]peer.ID, error)
    80  }
    81  
    82  // module contains all components necessary to access information and
    83  // perform actions related to the node's p2p Host / operations.
    84  type module struct {
    85  	host      HostBase
    86  	ps        *pubsub.PubSub
    87  	connGater *conngater.BasicConnectionGater
    88  	bw        *metrics.BandwidthCounter
    89  	rm        network.ResourceManager
    90  }
    91  
    92  func newModule(
    93  	host HostBase,
    94  	ps *pubsub.PubSub,
    95  	cg *conngater.BasicConnectionGater,
    96  	bw *metrics.BandwidthCounter,
    97  	rm network.ResourceManager,
    98  ) Module {
    99  	return &module{
   100  		host:      host,
   101  		ps:        ps,
   102  		connGater: cg,
   103  		bw:        bw,
   104  		rm:        rm,
   105  	}
   106  }
   107  
   108  func (m *module) Info(context.Context) (peer.AddrInfo, error) {
   109  	return *libhost.InfoFromHost(m.host), nil
   110  }
   111  
   112  func (m *module) Peers(context.Context) ([]peer.ID, error) {
   113  	return m.host.Network().Peers(), nil
   114  }
   115  
   116  func (m *module) PeerInfo(_ context.Context, id peer.ID) (peer.AddrInfo, error) {
   117  	return m.host.Peerstore().PeerInfo(id), nil
   118  }
   119  
   120  func (m *module) Connect(ctx context.Context, pi peer.AddrInfo) error {
   121  	return m.host.Connect(ctx, pi)
   122  }
   123  
   124  func (m *module) ClosePeer(_ context.Context, id peer.ID) error {
   125  	return m.host.Network().ClosePeer(id)
   126  }
   127  
   128  func (m *module) Connectedness(_ context.Context, id peer.ID) (network.Connectedness, error) {
   129  	return m.host.Network().Connectedness(id), nil
   130  }
   131  
   132  func (m *module) NATStatus(context.Context) (network.Reachability, error) {
   133  	basic, ok := m.host.(*basichost.BasicHost)
   134  	if !ok {
   135  		return 0, fmt.Errorf("unexpected implementation of host.Host, expected %s, got %T",
   136  			reflect.TypeOf(&basichost.BasicHost{}).String(), m.host)
   137  	}
   138  	return basic.GetAutoNat().Status(), nil
   139  }
   140  
   141  func (m *module) BlockPeer(_ context.Context, p peer.ID) error {
   142  	return m.connGater.BlockPeer(p)
   143  }
   144  
   145  func (m *module) UnblockPeer(_ context.Context, p peer.ID) error {
   146  	return m.connGater.UnblockPeer(p)
   147  }
   148  
   149  func (m *module) ListBlockedPeers(context.Context) ([]peer.ID, error) {
   150  	return m.connGater.ListBlockedPeers(), nil
   151  }
   152  
   153  func (m *module) Protect(_ context.Context, id peer.ID, tag string) error {
   154  	m.host.ConnManager().Protect(id, tag)
   155  	return nil
   156  }
   157  
   158  func (m *module) Unprotect(_ context.Context, id peer.ID, tag string) (bool, error) {
   159  	return m.host.ConnManager().Unprotect(id, tag), nil
   160  }
   161  
   162  func (m *module) IsProtected(_ context.Context, id peer.ID, tag string) (bool, error) {
   163  	return m.host.ConnManager().IsProtected(id, tag), nil
   164  }
   165  
   166  func (m *module) BandwidthStats(context.Context) (metrics.Stats, error) {
   167  	return m.bw.GetBandwidthTotals(), nil
   168  }
   169  
   170  func (m *module) BandwidthForPeer(_ context.Context, id peer.ID) (metrics.Stats, error) {
   171  	return m.bw.GetBandwidthForPeer(id), nil
   172  }
   173  
   174  func (m *module) BandwidthForProtocol(_ context.Context, proto protocol.ID) (metrics.Stats, error) {
   175  	return m.bw.GetBandwidthForProtocol(proto), nil
   176  }
   177  
   178  func (m *module) ResourceState(context.Context) (rcmgr.ResourceManagerStat, error) {
   179  	rms, ok := m.rm.(rcmgr.ResourceManagerState)
   180  	if !ok {
   181  		return rcmgr.ResourceManagerStat{}, fmt.Errorf("network.resourceManager does not implement " +
   182  			"rcmgr.ResourceManagerState")
   183  	}
   184  	return rms.Stat(), nil
   185  }
   186  
   187  func (m *module) PubSubPeers(_ context.Context, topic string) ([]peer.ID, error) {
   188  	return m.ps.ListPeers(topic), nil
   189  }
   190  
   191  // API is a wrapper around Module for the RPC.
   192  // TODO(@distractedm1nd): These structs need to be autogenerated.
   193  //
   194  //nolint:dupl
   195  type API struct {
   196  	Internal struct {
   197  		Info                 func(context.Context) (peer.AddrInfo, error)                         `perm:"admin"`
   198  		Peers                func(context.Context) ([]peer.ID, error)                             `perm:"admin"`
   199  		PeerInfo             func(ctx context.Context, id peer.ID) (peer.AddrInfo, error)         `perm:"admin"`
   200  		Connect              func(ctx context.Context, pi peer.AddrInfo) error                    `perm:"admin"`
   201  		ClosePeer            func(ctx context.Context, id peer.ID) error                          `perm:"admin"`
   202  		Connectedness        func(ctx context.Context, id peer.ID) (network.Connectedness, error) `perm:"admin"`
   203  		NATStatus            func(context.Context) (network.Reachability, error)                  `perm:"admin"`
   204  		BlockPeer            func(ctx context.Context, p peer.ID) error                           `perm:"admin"`
   205  		UnblockPeer          func(ctx context.Context, p peer.ID) error                           `perm:"admin"`
   206  		ListBlockedPeers     func(context.Context) ([]peer.ID, error)                             `perm:"admin"`
   207  		Protect              func(ctx context.Context, id peer.ID, tag string) error              `perm:"admin"`
   208  		Unprotect            func(ctx context.Context, id peer.ID, tag string) (bool, error)      `perm:"admin"`
   209  		IsProtected          func(ctx context.Context, id peer.ID, tag string) (bool, error)      `perm:"admin"`
   210  		BandwidthStats       func(context.Context) (metrics.Stats, error)                         `perm:"admin"`
   211  		BandwidthForPeer     func(ctx context.Context, id peer.ID) (metrics.Stats, error)         `perm:"admin"`
   212  		BandwidthForProtocol func(ctx context.Context, proto protocol.ID) (metrics.Stats, error)  `perm:"admin"`
   213  		ResourceState        func(context.Context) (rcmgr.ResourceManagerStat, error)             `perm:"admin"`
   214  		PubSubPeers          func(ctx context.Context, topic string) ([]peer.ID, error)           `perm:"admin"`
   215  	}
   216  }
   217  
   218  func (api *API) Info(ctx context.Context) (peer.AddrInfo, error) {
   219  	return api.Internal.Info(ctx)
   220  }
   221  
   222  func (api *API) Peers(ctx context.Context) ([]peer.ID, error) {
   223  	return api.Internal.Peers(ctx)
   224  }
   225  
   226  func (api *API) PeerInfo(ctx context.Context, id peer.ID) (peer.AddrInfo, error) {
   227  	return api.Internal.PeerInfo(ctx, id)
   228  }
   229  
   230  func (api *API) Connect(ctx context.Context, pi peer.AddrInfo) error {
   231  	return api.Internal.Connect(ctx, pi)
   232  }
   233  
   234  func (api *API) ClosePeer(ctx context.Context, id peer.ID) error {
   235  	return api.Internal.ClosePeer(ctx, id)
   236  }
   237  
   238  func (api *API) Connectedness(ctx context.Context, id peer.ID) (network.Connectedness, error) {
   239  	return api.Internal.Connectedness(ctx, id)
   240  }
   241  
   242  func (api *API) NATStatus(ctx context.Context) (network.Reachability, error) {
   243  	return api.Internal.NATStatus(ctx)
   244  }
   245  
   246  func (api *API) BlockPeer(ctx context.Context, p peer.ID) error {
   247  	return api.Internal.BlockPeer(ctx, p)
   248  }
   249  
   250  func (api *API) UnblockPeer(ctx context.Context, p peer.ID) error {
   251  	return api.Internal.UnblockPeer(ctx, p)
   252  }
   253  
   254  func (api *API) ListBlockedPeers(ctx context.Context) ([]peer.ID, error) {
   255  	return api.Internal.ListBlockedPeers(ctx)
   256  }
   257  
   258  func (api *API) Protect(ctx context.Context, id peer.ID, tag string) error {
   259  	return api.Internal.Protect(ctx, id, tag)
   260  }
   261  
   262  func (api *API) Unprotect(ctx context.Context, id peer.ID, tag string) (bool, error) {
   263  	return api.Internal.Unprotect(ctx, id, tag)
   264  }
   265  
   266  func (api *API) IsProtected(ctx context.Context, id peer.ID, tag string) (bool, error) {
   267  	return api.Internal.IsProtected(ctx, id, tag)
   268  }
   269  
   270  func (api *API) BandwidthStats(ctx context.Context) (metrics.Stats, error) {
   271  	return api.Internal.BandwidthStats(ctx)
   272  }
   273  
   274  func (api *API) BandwidthForPeer(ctx context.Context, id peer.ID) (metrics.Stats, error) {
   275  	return api.Internal.BandwidthForPeer(ctx, id)
   276  }
   277  
   278  func (api *API) BandwidthForProtocol(ctx context.Context, proto protocol.ID) (metrics.Stats, error) {
   279  	return api.Internal.BandwidthForProtocol(ctx, proto)
   280  }
   281  
   282  func (api *API) ResourceState(ctx context.Context) (rcmgr.ResourceManagerStat, error) {
   283  	return api.Internal.ResourceState(ctx)
   284  }
   285  
   286  func (api *API) PubSubPeers(ctx context.Context, topic string) ([]peer.ID, error) {
   287  	return api.Internal.PubSubPeers(ctx, topic)
   288  }