swarm

package
v0.0.2-replace Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 27, 2024 License: MIT Imports: 32 Imported by: 1

Documentation

Index

Constants

View Source
const (
	// duration by which TCP dials are delayed relative to the last QUIC dial
	PublicTCPDelay  = 250 * time.Millisecond
	PrivateTCPDelay = 30 * time.Millisecond

	// duration by which QUIC dials are delayed relative to previous QUIC dial
	PublicQUICDelay  = 250 * time.Millisecond
	PrivateQUICDelay = 30 * time.Millisecond

	// RelayDelay is the duration by which relay dials are delayed relative to direct addresses
	RelayDelay = 500 * time.Millisecond
)

The 250ms value is from happy eyeballs RFC 8305. This is a rough estimate of 1 RTT

View Source
const ConcurrentFdDials = 160

ConcurrentFdDials is the number of concurrent outbound dials over transports that consume file descriptors

View Source
const DialAttempts = 1

DialAttempts governs how many times a goroutine will try to dial a given peer. Note: this is down to one, as we have _too many dials_ atm. To add back in, add loop back in Dial(.)

Variables

View Source
var (
	// ErrDialBackoff is returned by the backoff code when a given peer has
	// been dialed too frequently
	ErrDialBackoff = errors.New("dial backoff")

	// ErrDialRefusedBlackHole is returned when we are in a black holed environment
	ErrDialRefusedBlackHole = errors.New("dial refused because of black hole")

	// ErrDialToSelf is returned if we attempt to dial our own peer
	ErrDialToSelf = errors.New("dial to self attempted")

	// ErrNoTransport is returned when we don't know a transport for the
	// given multiaddr.
	ErrNoTransport = errors.New("no transport for protocol")

	// ErrAllDialsFailed is returned when connecting to a peer has ultimately failed
	ErrAllDialsFailed = errors.New("all dials failed")

	// ErrNoAddresses is returned when we fail to find any addresses for a
	// peer we're trying to dial.
	ErrNoAddresses = errors.New("no addresses")

	// ErrNoGoodAddresses is returned when we find addresses for a peer but
	// can't use any of them.
	ErrNoGoodAddresses = errors.New("no good addresses")

	// ErrGaterDisallowedConnection is returned when the gater prevents us from
	// forming a connection with a peer.
	ErrGaterDisallowedConnection = errors.New("gater disallows connection to peer")
)
View Source
var BackoffBase = time.Second * 5

BackoffBase is the base amount of time to backoff (default: 5s).

View Source
var BackoffCoef = time.Second

BackoffCoef is the backoff coefficient (default: 1s).

View Source
var BackoffMax = time.Minute * 5

BackoffMax is the maximum backoff time (default: 5m).

View Source
var DefaultPerPeerRateLimit = 8

DefaultPerPeerRateLimit is the number of concurrent outbound dials to make per peer

View Source
var ErrAddrFiltered = errors.New("address filtered")

ErrAddrFiltered is returned when trying to register a connection to a filtered address. You shouldn't see this error unless some underlying transport is misbehaving.

View Source
var ErrConnClosed = errors.New("connection closed")

ErrConnClosed is returned when operating on a closed connection.

View Source
var ErrDialTimeout = errors.New("dial timed out")

ErrDialTimeout is returned when one a dial times out due to the global timeout

View Source
var ErrQUICDraft29 errQUICDraft29

ErrQUICDraft29 wraps ErrNoTransport and provide a more meaningful error message

View Source
var ErrSwarmClosed = errors.New("swarm closed")

ErrSwarmClosed is returned when one attempts to operate on a closed swarm.

Functions

func DefaultDialRanker

func DefaultDialRanker(addrs []ma.Multiaddr) []network.AddrDelay

DefaultDialRanker determines the ranking of outgoing connection attempts.

Addresses are grouped into three distinct groups:

  • private addresses (localhost and local networks (RFC 1918))
  • public addresses
  • relay addresses

Within each group, the addresses are ranked according to the ranking logic described below. We then dial addresses according to this ranking, with short timeouts applied between dial attempts. This ranking logic dramatically reduces the number of simultaneous dial attempts, while introducing no additional latency in the vast majority of cases.

Private and public address groups are dialed in parallel. Dialing relay addresses is delayed by 500 ms, if we have any non-relay alternatives.

Within each group (private, public, relay addresses) we apply the following ranking logic:

  1. If both IPv6 QUIC and IPv4 QUIC addresses are present, we do a Happy Eyeballs RFC 8305 style ranking. First dial the IPv6 QUIC address with the lowest port. After this we dial the IPv4 QUIC address with the lowest port delayed by 250ms (PublicQUICDelay) for public addresses, and 30ms (PrivateQUICDelay) for local addresses. After this we dial all the rest of the addresses delayed by 250ms (PublicQUICDelay) for public addresses, and 30ms (PrivateQUICDelay) for local addresses.
  2. If only one of QUIC IPv6 or QUIC IPv4 addresses are present, dial the QUIC address with the lowest port first. After this we dial the rest of the QUIC addresses delayed by 250ms (PublicQUICDelay) for public addresses, and 30ms (PrivateQUICDelay) for local addresses.
  3. If a QUIC or WebTransport address is present, TCP addresses dials are delayed relative to the last QUIC dial: We prefer to end up with a QUIC connection. For public addresses, the delay introduced is 250ms (PublicTCPDelay), and for private addresses 30ms (PrivateTCPDelay).
  4. For the TCP addresses we follow a strategy similar to QUIC with an optimisation for handling the long TCP handshake time described in 6. If both IPv6 TCP and IPv4 TCP addresses are present, we do a Happy Eyeballs style ranking. First dial the IPv6 TCP address with the lowest port. After this, dial the IPv4 TCP address with the lowest port delayed by 250ms (PublicTCPDelay) for public addresses, and 30ms (PrivateTCPDelay) for local addresses. After this we dial all the rest of the addresses delayed by 250ms (PublicTCPDelay) for public addresses, and 30ms (PrivateTCPDelay) for local addresses.
  5. If only one of TCP IPv6 or TCP IPv4 addresses are present, dial the TCP address with the lowest port first. After this we dial the rest of the TCP addresses delayed by 250ms (PublicTCPDelay) for public addresses, and 30ms (PrivateTCPDelay) for local addresses.
  6. When a TCP socket is connected and awaiting security and muxer upgrade, we stop new dials for 2*PrivateTCPDelay to allow for the upgrade to complete.

We dial lowest ports first as they are more likely to be the listen port.

func NoDelayDialRanker

func NoDelayDialRanker(addrs []ma.Multiaddr) []network.AddrDelay

NoDelayDialRanker ranks addresses with no delay. This is useful for simultaneous connect requests.

Types

type Clock

type Clock interface {
	Now() time.Time
	Since(t time.Time) time.Duration
	InstantTimer(when time.Time) InstantTimer
}

Clock is a clock that can create timers that trigger at some instant rather than some duration

type Conn

type Conn struct {
	// contains filtered or unexported fields
}

Conn is the connection type used by swarm. In general, you won't use this type directly.

func (*Conn) Close

func (c *Conn) Close() error

Close closes this connection.

Note: This method won't wait for the close notifications to finish as that would create a deadlock when called from an open notification (because all open notifications must finish before we can fire off the close notifications).

func (*Conn) ConnState

func (c *Conn) ConnState() network.ConnectionState

ConnState is the security connection state. including early data result. Empty if not supported.

func (*Conn) GetStreams

func (c *Conn) GetStreams() []network.Stream

GetStreams returns the streams associated with this connection.

func (*Conn) ID

func (c *Conn) ID() string

func (*Conn) IsClosed

func (c *Conn) IsClosed() bool

func (*Conn) LocalMultiaddr

func (c *Conn) LocalMultiaddr() ma.Multiaddr

LocalMultiaddr is the Multiaddr on this side

func (*Conn) LocalPeer

func (c *Conn) LocalPeer() peer.ID

LocalPeer is the Peer on our side of the connection

func (*Conn) NewStream

func (c *Conn) NewStream(ctx context.Context) (network.Stream, error)

NewStream returns a new Stream from this connection

func (*Conn) RemoteMultiaddr

func (c *Conn) RemoteMultiaddr() ma.Multiaddr

RemoteMultiaddr is the Multiaddr on the remote side

func (*Conn) RemotePeer

func (c *Conn) RemotePeer() peer.ID

RemotePeer is the Peer on the remote side

func (*Conn) RemotePublicKey

func (c *Conn) RemotePublicKey() ic.PubKey

RemotePublicKey is the public key of the peer on the remote side

func (*Conn) Scope

func (c *Conn) Scope() network.ConnScope

func (*Conn) Stat

func (c *Conn) Stat() network.ConnStats

Stat returns metadata pertaining to this connection

func (*Conn) String

func (c *Conn) String() string

type DialBackoff

type DialBackoff struct {
	// contains filtered or unexported fields
}

DialBackoff is a type for tracking peer dial backoffs. Dialbackoff is used to avoid over-dialing the same, dead peers. Whenever we totally time out on all addresses of a peer, we add the addresses to DialBackoff. Then, whenever we attempt to dial the peer again, we check each address for backoff. If it's on backoff, we don't dial the address and exit promptly. If a dial is successful, the peer and all its addresses are removed from backoff.

* It's safe to use its zero value. * It's thread-safe. * It's *not* safe to move this type after using.

func (*DialBackoff) AddBackoff

func (db *DialBackoff) AddBackoff(p peer.ID, addr ma.Multiaddr)

AddBackoff adds peer's address to backoff.

Backoff is not exponential, it's quadratic and computed according to the following formula:

BackoffBase + BakoffCoef * PriorBackoffs^2

Where PriorBackoffs is the number of previous backoffs.

func (*DialBackoff) Backoff

func (db *DialBackoff) Backoff(p peer.ID, addr ma.Multiaddr) (backoff bool)

Backoff returns whether the client should backoff from dialing peer p at address addr

func (*DialBackoff) Clear

func (db *DialBackoff) Clear(p peer.ID)

Clear removes a backoff record. Clients should call this after a successful Dial.

type DialError

type DialError struct {
	Peer       peer.ID
	DialErrors []TransportError
	Cause      error
	Skipped    int
}

DialError is the error type returned when dialing.

func (*DialError) Error

func (e *DialError) Error() string

func (*DialError) Timeout

func (e *DialError) Timeout() bool

func (*DialError) Unwrap

func (e *DialError) Unwrap() []error

type InstantTimer

type InstantTimer interface {
	Reset(d time.Time) bool
	Stop() bool
	Ch() <-chan time.Time
}

InstantTimer is a timer that triggers at some instant rather than some duration

type MetricsTracer

type MetricsTracer interface {
	OpenedConnection(network.Direction, crypto.PubKey, network.ConnectionState, ma.Multiaddr)
	ClosedConnection(network.Direction, time.Duration, network.ConnectionState, ma.Multiaddr)
	CompletedHandshake(time.Duration, network.ConnectionState, ma.Multiaddr)
	FailedDialing(ma.Multiaddr, error, error)
	DialCompleted(success bool, totalDials int)
	DialRankingDelay(d time.Duration)
	UpdatedBlackHoleFilterState(name string, state blackHoleState, nextProbeAfter int, successFraction float64)
}

func NewMetricsTracer

func NewMetricsTracer(opts ...MetricsTracerOption) MetricsTracer

type MetricsTracerOption

type MetricsTracerOption func(*metricsTracerSetting)

type Option

type Option func(*Swarm) error

func WithConnectionGater

func WithConnectionGater(gater connmgr.ConnectionGater) Option

WithConnectionGater sets a connection gater

func WithDialRanker

func WithDialRanker(d network.DialRanker) Option

WithDialRanker configures swarm to use d as the DialRanker

func WithDialTimeout

func WithDialTimeout(t time.Duration) Option

func WithDialTimeoutLocal

func WithDialTimeoutLocal(t time.Duration) Option

func WithIPv6BlackHoleConfig

func WithIPv6BlackHoleConfig(enabled bool, n, min int) Option

WithIPv6BlackHoleConfig configures swarm to use c as the config for IPv6 black hole detection n is the size of the sliding window used to evaluate black hole state min is the minimum number of successes out of n required to not block requests

func WithMetrics

func WithMetrics(reporter metrics.Reporter) Option

WithMetrics sets a metrics reporter

func WithMetricsTracer

func WithMetricsTracer(t MetricsTracer) Option

func WithMultiaddrResolver

func WithMultiaddrResolver(maResolver *madns.Resolver) Option

WithMultiaddrResolver sets a custom multiaddress resolver

func WithResourceManager

func WithResourceManager(m network.ResourceManager) Option

func WithUDPBlackHoleConfig

func WithUDPBlackHoleConfig(enabled bool, n, min int) Option

WithUDPBlackHoleConfig configures swarm to use c as the config for UDP black hole detection n is the size of the sliding window used to evaluate black hole state min is the minimum number of successes out of n required to not block requests

type RealClock

type RealClock struct{}

func (RealClock) InstantTimer

func (RealClock) InstantTimer(when time.Time) InstantTimer

func (RealClock) Now

func (RealClock) Now() time.Time

func (RealClock) Since

func (RealClock) Since(t time.Time) time.Duration

type RealTimer

type RealTimer struct {
	// contains filtered or unexported fields
}

func (RealTimer) Ch

func (t RealTimer) Ch() <-chan time.Time

func (RealTimer) Reset

func (t RealTimer) Reset(d time.Time) bool

func (RealTimer) Stop

func (t RealTimer) Stop() bool

type Stream

type Stream struct {
	// contains filtered or unexported fields
}

Stream is the stream type used by swarm. In general, you won't use this type directly.

func (*Stream) Close

func (s *Stream) Close() error

Close closes the stream, closing both ends and freeing all associated resources.

func (*Stream) CloseRead

func (s *Stream) CloseRead() error

CloseRead closes the stream for reading. This function does not free resources, call Close or Reset when done with the stream.

func (*Stream) CloseWrite

func (s *Stream) CloseWrite() error

CloseWrite closes the stream for writing, flushing all data and sending an EOF. This function does not free resources, call Close or Reset when done with the stream.

func (*Stream) Conn

func (s *Stream) Conn() network.Conn

Conn returns the Conn associated with this stream, as an network.Conn

func (*Stream) ID

func (s *Stream) ID() string

func (*Stream) Protocol

func (s *Stream) Protocol() protocol.ID

Protocol returns the protocol negotiated on this stream (if set).

func (*Stream) Read

func (s *Stream) Read(p []byte) (int, error)

Read reads bytes from a stream.

func (*Stream) Reset

func (s *Stream) Reset() error

Reset resets the stream, signaling an error on both ends and freeing all associated resources.

func (*Stream) Scope

func (s *Stream) Scope() network.StreamScope

func (*Stream) SetDeadline

func (s *Stream) SetDeadline(t time.Time) error

SetDeadline sets the read and write deadlines for this stream.

func (*Stream) SetProtocol

func (s *Stream) SetProtocol(p protocol.ID) error

SetProtocol sets the protocol for this stream.

This doesn't actually *do* anything other than record the fact that we're speaking the given protocol over this stream. It's still up to the user to negotiate the protocol. This is usually done by the Host.

func (*Stream) SetReadDeadline

func (s *Stream) SetReadDeadline(t time.Time) error

SetReadDeadline sets the read deadline for this stream.

func (*Stream) SetWriteDeadline

func (s *Stream) SetWriteDeadline(t time.Time) error

SetWriteDeadline sets the write deadline for this stream.

func (*Stream) Stat

func (s *Stream) Stat() network.Stats

Stat returns metadata information for this stream.

func (*Stream) String

func (s *Stream) String() string

func (*Stream) Write

func (s *Stream) Write(p []byte) (int, error)

Write writes bytes to a stream, flushing for each call.

type Swarm

type Swarm struct {
	// contains filtered or unexported fields
}

Swarm is a connection muxer, allowing connections to other peers to be opened and closed, while still using the same Chan for all communication. The Chan sends/receives Messages, which note the destination or source Peer.

func NewSwarm

func NewSwarm(local peer.ID, peers peerstore.Peerstore, eventBus event.Bus, opts ...Option) (*Swarm, error)

NewSwarm constructs a Swarm.

func (*Swarm) AddListenAddr

func (s *Swarm) AddListenAddr(a ma.Multiaddr) error

AddListenAddr tells the swarm to listen on a single address. Unlike Listen, this method does not attempt to filter out bad addresses.

func (*Swarm) AddTransport

func (s *Swarm) AddTransport(t transport.Transport) error

AddTransport adds a transport to this swarm.

Satisfies the Network interface from go-libp2p-transport.

func (*Swarm) Backoff

func (s *Swarm) Backoff() *DialBackoff

Backoff returns the DialBackoff object for this swarm.

func (*Swarm) Close

func (s *Swarm) Close() error

func (*Swarm) ClosePeer

func (s *Swarm) ClosePeer(p peer.ID) error

ClosePeer closes all connections to the given peer.

func (*Swarm) Connectedness

func (s *Swarm) Connectedness(p peer.ID) network.Connectedness

Connectedness returns our "connectedness" state with the given peer.

To check if we have an open connection, use `s.Connectedness(p) == network.Connected`.

func (*Swarm) Conns

func (s *Swarm) Conns() []network.Conn

Conns returns a slice of all connections.

func (*Swarm) ConnsToPeer

func (s *Swarm) ConnsToPeer(p peer.ID) []network.Conn

ConnsToPeer returns all the live connections to peer.

func (*Swarm) DialPeer

func (s *Swarm) DialPeer(ctx context.Context, p peer.ID) (network.Conn, error)

DialPeer connects to a peer. Use network.WithForceDirectDial to force a direct connection.

The idea is that the client of Swarm does not need to know what network the connection will happen over. Swarm can use whichever it choses. This allows us to use various transport protocols, do NAT traversal/relay, etc. to achieve connection.

func (*Swarm) InterfaceListenAddresses

func (s *Swarm) InterfaceListenAddresses() ([]ma.Multiaddr, error)

InterfaceListenAddresses returns a list of addresses at which this swarm listens. It expands "any interface" addresses (/ip4/0.0.0.0, /ip6/::) to use the known local interfaces.

func (*Swarm) Listen

func (s *Swarm) Listen(addrs ...ma.Multiaddr) error

Listen sets up listeners for all of the given addresses. It returns as long as we successfully listen on at least *one* address.

func (*Swarm) ListenAddresses

func (s *Swarm) ListenAddresses() []ma.Multiaddr

ListenAddresses returns a list of addresses at which this swarm listens.

func (*Swarm) ListenClose

func (s *Swarm) ListenClose(addrs ...ma.Multiaddr)

ListenClose stop and delete listeners for all of the given addresses. If an any address belongs to one of the addreses a Listener provides, then the Listener will close for *all* addresses it provides. For example if you close and address with `/quic`, then the QUIC listener will close and also close any `/quic-v1` address.

func (*Swarm) LocalPeer

func (s *Swarm) LocalPeer() peer.ID

LocalPeer returns the local peer swarm is associated to.

func (*Swarm) NewStream

func (s *Swarm) NewStream(ctx context.Context, p peer.ID) (network.Stream, error)

NewStream creates a new stream on any available connection to peer, dialing if necessary. Use network.WithUseTransient to open a stream over a transient(relayed) connection.

func (*Swarm) Notify

func (s *Swarm) Notify(f network.Notifiee)

Notify signs up Notifiee to receive signals when events happen

func (*Swarm) Peers

func (s *Swarm) Peers() []peer.ID

Peers returns a copy of the set of peers swarm is connected to.

func (*Swarm) Peerstore

func (s *Swarm) Peerstore() peerstore.Peerstore

Peerstore returns this swarms internal Peerstore.

func (*Swarm) ResourceManager

func (s *Swarm) ResourceManager() network.ResourceManager

func (*Swarm) SetStreamHandler

func (s *Swarm) SetStreamHandler(handler network.StreamHandler)

SetStreamHandler assigns the handler for new streams.

func (*Swarm) StopNotify

func (s *Swarm) StopNotify(f network.Notifiee)

StopNotify unregisters Notifiee fromr receiving signals

func (*Swarm) StreamHandler

func (s *Swarm) StreamHandler() network.StreamHandler

StreamHandler gets the handler for new streams.

func (*Swarm) String

func (s *Swarm) String() string

String returns a string representation of Network.

func (*Swarm) TransportForDialing

func (s *Swarm) TransportForDialing(a ma.Multiaddr) transport.Transport

TransportForDialing retrieves the appropriate transport for dialing the given multiaddr.

func (*Swarm) TransportForListening

func (s *Swarm) TransportForListening(a ma.Multiaddr) transport.Transport

TransportForListening retrieves the appropriate transport for listening on the given multiaddr.

type TransportError

type TransportError struct {
	Address ma.Multiaddr
	Cause   error
}

TransportError is the error returned when dialing a specific address.

func (*TransportError) Error

func (e *TransportError) Error() string

func (*TransportError) Unwrap

func (e *TransportError) Unwrap() error

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL