github.com/ethersphere/bee/v2@v2.2.0/pkg/p2p/p2p.go (about)

     1  // Copyright 2020 The Swarm Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package p2p provides the peer-to-peer abstractions used
     6  // across different protocols in Bee.
     7  package p2p
     8  
     9  import (
    10  	"context"
    11  	"errors"
    12  	"fmt"
    13  	"io"
    14  	"time"
    15  
    16  	"github.com/ethersphere/bee/v2/pkg/bzz"
    17  	"github.com/ethersphere/bee/v2/pkg/swarm"
    18  	"github.com/libp2p/go-libp2p/core/network"
    19  	ma "github.com/multiformats/go-multiaddr"
    20  )
    21  
    22  // ReachabilityStatus represents the node reachability status.
    23  type ReachabilityStatus network.Reachability
    24  
    25  // String implements the fmt.Stringer interface.
    26  func (rs ReachabilityStatus) String() string {
    27  	return network.Reachability(rs).String()
    28  }
    29  
    30  const (
    31  	ReachabilityStatusUnknown = ReachabilityStatus(network.ReachabilityUnknown)
    32  	ReachabilityStatusPublic  = ReachabilityStatus(network.ReachabilityPublic)
    33  	ReachabilityStatusPrivate = ReachabilityStatus(network.ReachabilityPrivate)
    34  )
    35  
    36  // NetworkStatus represents the network availability status.
    37  type NetworkStatus int
    38  
    39  // String implements the fmt.Stringer interface.
    40  func (ns NetworkStatus) String() string {
    41  	str := [...]string{
    42  		NetworkStatusUnknown:     "Unknown",
    43  		NetworkStatusAvailable:   "Available",
    44  		NetworkStatusUnavailable: "Unavailable",
    45  	}
    46  	if ns < 0 || int(ns) >= len(str) {
    47  		return "(unrecognized)"
    48  	}
    49  	return str[ns]
    50  }
    51  
    52  const (
    53  	NetworkStatusUnknown     NetworkStatus = 0
    54  	NetworkStatusAvailable   NetworkStatus = 1
    55  	NetworkStatusUnavailable NetworkStatus = 2
    56  )
    57  
    58  var ErrNetworkUnavailable = errors.New("network unavailable")
    59  
    60  // Service provides methods to handle p2p Peers and Protocols.
    61  type Service interface {
    62  	AddProtocol(ProtocolSpec) error
    63  	// Connect to a peer but do not notify topology about the established connection.
    64  	Connect(ctx context.Context, addr ma.Multiaddr) (address *bzz.Address, err error)
    65  	Disconnecter
    66  	Peers() []Peer
    67  	Blocklisted(swarm.Address) (bool, error)
    68  	BlocklistedPeers() ([]BlockListedPeer, error)
    69  	Addresses() ([]ma.Multiaddr, error)
    70  	SetPickyNotifier(PickyNotifier)
    71  	Halter
    72  	NetworkStatuser
    73  }
    74  
    75  // NetworkStatuser handles bookkeeping of the network availability status.
    76  type NetworkStatuser interface {
    77  	// NetworkStatus returns current network availability status.
    78  	NetworkStatus() NetworkStatus
    79  }
    80  
    81  type Disconnecter interface {
    82  	Disconnect(overlay swarm.Address, reason string) error
    83  	Blocklister
    84  }
    85  
    86  type Blocklister interface {
    87  	NetworkStatuser
    88  
    89  	// Blocklist will disconnect a peer and put it on a blocklist (blocking in & out connections) for provided duration
    90  	// Duration 0 is treated as an infinite duration.
    91  	Blocklist(overlay swarm.Address, duration time.Duration, reason string) error
    92  }
    93  
    94  type Halter interface {
    95  	// Halt new incoming connections while shutting down
    96  	Halt()
    97  }
    98  
    99  // PickyNotifier can decide whether a peer should be picked
   100  type PickyNotifier interface {
   101  	Picker
   102  	Notifier
   103  	ReachabilityUpdater
   104  	ReachableNotifier
   105  }
   106  
   107  type Picker interface {
   108  	Pick(Peer) bool
   109  }
   110  
   111  type ReachableNotifier interface {
   112  	Reachable(swarm.Address, ReachabilityStatus)
   113  }
   114  
   115  type Reacher interface {
   116  	Connected(swarm.Address, ma.Multiaddr)
   117  	Disconnected(swarm.Address)
   118  	Close() error
   119  }
   120  
   121  type ReachabilityUpdater interface {
   122  	UpdateReachability(ReachabilityStatus)
   123  }
   124  
   125  type Notifier interface {
   126  	Connected(context.Context, Peer, bool) error
   127  	Disconnected(Peer)
   128  	Announce(ctx context.Context, peer swarm.Address, fullnode bool) error
   129  	AnnounceTo(ctx context.Context, addressee, peer swarm.Address, fullnode bool) error
   130  }
   131  
   132  // DebugService extends the Service with method used for debugging.
   133  type DebugService interface {
   134  	Service
   135  	SetWelcomeMessage(val string) error
   136  	GetWelcomeMessage() string
   137  }
   138  
   139  // Streamer is able to create a new Stream.
   140  type Streamer interface {
   141  	NewStream(ctx context.Context, address swarm.Address, h Headers, protocol, version, stream string) (Stream, error)
   142  }
   143  
   144  type StreamerDisconnecter interface {
   145  	Streamer
   146  	Disconnecter
   147  }
   148  
   149  // Pinger interface is used to ping a underlay address which is not yet known to the bee node.
   150  // It uses libp2p's default ping protocol. This is different from the PingPong protocol as this
   151  // is meant to be used before we know a particular underlay and we can consider it useful
   152  type Pinger interface {
   153  	Ping(ctx context.Context, addr ma.Multiaddr) (rtt time.Duration, err error)
   154  }
   155  
   156  type StreamerPinger interface {
   157  	Streamer
   158  	Pinger
   159  }
   160  
   161  // Stream represent a bidirectional data Stream.
   162  type Stream interface {
   163  	io.ReadWriter
   164  	io.Closer
   165  	ResponseHeaders() Headers
   166  	Headers() Headers
   167  	FullClose() error
   168  	Reset() error
   169  }
   170  
   171  // ProtocolSpec defines a collection of Stream specifications with handlers.
   172  type ProtocolSpec struct {
   173  	Name          string
   174  	Version       string
   175  	StreamSpecs   []StreamSpec
   176  	ConnectIn     func(context.Context, Peer) error
   177  	ConnectOut    func(context.Context, Peer) error
   178  	DisconnectIn  func(Peer) error
   179  	DisconnectOut func(Peer) error
   180  }
   181  
   182  // StreamSpec defines a Stream handling within the protocol.
   183  type StreamSpec struct {
   184  	Name    string
   185  	Handler HandlerFunc
   186  	Headler HeadlerFunc
   187  }
   188  
   189  // Peer holds information about a Peer.
   190  type Peer struct {
   191  	Address         swarm.Address
   192  	FullNode        bool
   193  	EthereumAddress []byte
   194  }
   195  
   196  // BlockListedPeer holds information about a Peer that is blocked.
   197  type BlockListedPeer struct {
   198  	Peer
   199  	Reason   string
   200  	Duration time.Duration
   201  }
   202  
   203  // HandlerFunc handles a received Stream from a Peer.
   204  type HandlerFunc func(context.Context, Peer, Stream) error
   205  
   206  // HandlerMiddleware decorates a HandlerFunc by returning a new one.
   207  type HandlerMiddleware func(HandlerFunc) HandlerFunc
   208  
   209  // HeadlerFunc is returning response headers based on the received request
   210  // headers.
   211  type HeadlerFunc func(Headers, swarm.Address) Headers
   212  
   213  // Headers represents a collection of p2p header key value pairs.
   214  type Headers map[string][]byte
   215  
   216  // Common header names.
   217  const (
   218  	HeaderNameTracingSpanContext = "tracing-span-context"
   219  )
   220  
   221  // NewSwarmStreamName constructs a libp2p compatible stream name out of
   222  // protocol name and version and stream name.
   223  func NewSwarmStreamName(protocol, version, stream string) string {
   224  	return "/swarm/" + protocol + "/" + version + "/" + stream
   225  }
   226  
   227  type ChunkDeliveryError struct {
   228  	msg string
   229  }
   230  
   231  // Error implements the error interface.
   232  func (e *ChunkDeliveryError) Error() string {
   233  	return fmt.Sprintf("delivery of chunk failed: %s", e.msg)
   234  }
   235  
   236  // NewChunkDeliveryError is a convenience constructor for ChunkDeliveryError.
   237  func NewChunkDeliveryError(msg string) error {
   238  	return &ChunkDeliveryError{msg: msg}
   239  }