network

package
v0.37.0 Latest Latest
Warning

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

Go to latest
Published: Oct 22, 2024 License: MIT Imports: 10 Imported by: 1,319

Documentation

Overview

Package network provides core networking abstractions for libp2p.

The network package provides the high-level Network interface for interacting with other libp2p peers, which is the primary public API for initiating and accepting connections to remote peers.

Index

Constants

View Source
const (
	// ReservationPriorityLow is a reservation priority that indicates a reservation if the scope
	// memory utilization is at 40% or less.
	ReservationPriorityLow uint8 = 101
	// Reservation PriorityMedium is a reservation priority that indicates a reservation if the scope
	// memory utilization is at 60% or less.
	ReservationPriorityMedium uint8 = 152
	// ReservationPriorityHigh is a reservation priority that indicates a reservation if the scope
	// memory utilization is at 80% or less.
	ReservationPriorityHigh uint8 = 203
	// ReservationPriorityAlways is a reservation priority that indicates a reservation if there is
	// enough memory, regardless of scope utilization.
	ReservationPriorityAlways uint8 = 255
)
View Source
const MessageSizeMax = 1 << 22 // 4 MB

MessageSizeMax is a soft (recommended) maximum for network messages. One can write more, as the interface is a stream. But it is useful to bunch it up into multiple read/writes when the whole message is a single, large serialized object.

Variables

View Source
var DialPeerTimeout = 60 * time.Second

DialPeerTimeout is the default timeout for a single call to `DialPeer`. When there are multiple concurrent calls to `DialPeer`, this timeout will apply to each independently.

View Source
var ErrLimitedConn = errors.New("limited connection to peer")

ErrLimitedConn is returned when attempting to open a stream to a peer with only a conn connection, without specifying the AllowLimitedConn option.

View Source
var ErrNoConn = errors.New("no usable connection to peer")

ErrNoConn is returned when attempting to open a stream to a peer with the NoDial option and no usable connection is available.

View Source
var ErrNoRemoteAddrs = errors.New("no remote addresses")

ErrNoRemoteAddrs is returned when there are no addresses associated with a peer during a dial.

View Source
var ErrReset = errors.New("stream reset")

ErrReset is returned when reading or writing on a reset stream.

View Source
var ErrResourceLimitExceeded = temporaryError("resource limit exceeded")

ErrResourceLimitExceeded is returned when attempting to perform an operation that would exceed system resource limits.

View Source
var ErrResourceScopeClosed = errors.New("resource scope closed")

ErrResourceScopeClosed is returned when attempting to reserve resources in a closed resource scope.

View Source
var ErrTransientConn = ErrLimitedConn

ErrTransientConn is returned when attempting to open a stream to a peer with only a transient connection, without specifying the UseTransient option.

Deprecated: Use ErrLimitedConn instead.

View Source
var GlobalNoopNotifiee = &NoopNotifiee{}

Global noop notifiee. Do not change.

Functions

func GetAllowLimitedConn added in v0.34.0

func GetAllowLimitedConn(ctx context.Context) (usetransient bool, reason string)

GetAllowLimitedConn returns true if the allow limited conn option is set in the context.

func GetDialPeerTimeout

func GetDialPeerTimeout(ctx context.Context) time.Duration

GetDialPeerTimeout returns the current DialPeer timeout (or the default).

func GetForceDirectDial

func GetForceDirectDial(ctx context.Context) (forceDirect bool, reason string)

EXPERIMENTAL GetForceDirectDial returns true if the force direct dial option is set in the context.

func GetNoDial

func GetNoDial(ctx context.Context) (nodial bool, reason string)

GetNoDial returns true if the no dial option is set in the context.

func GetSimultaneousConnect

func GetSimultaneousConnect(ctx context.Context) (simconnect bool, isClient bool, reason string)

GetSimultaneousConnect returns true if the simultaneous connect option is set in the context. EXPERIMENTAL

func GetUseTransient deprecated

func GetUseTransient(ctx context.Context) (usetransient bool, reason string)

GetUseTransient returns true if the use transient option is set in the context.

Deprecated: Use GetAllowLimitedConn instead.

func WithAllowLimitedConn added in v0.34.0

func WithAllowLimitedConn(ctx context.Context, reason string) context.Context

WithAllowLimitedConn constructs a new context with an option that instructs the network that it is acceptable to use a limited connection when opening a new stream.

func WithDialPeerTimeout

func WithDialPeerTimeout(ctx context.Context, timeout time.Duration) context.Context

WithDialPeerTimeout returns a new context with the DialPeer timeout applied.

This timeout overrides the default DialPeerTimeout and applies per-dial independently.

func WithForceDirectDial

func WithForceDirectDial(ctx context.Context, reason string) context.Context

EXPERIMENTAL WithForceDirectDial constructs a new context with an option that instructs the network to attempt to force a direct connection to a peer via a dial even if a proxied connection to it already exists.

func WithNoDial

func WithNoDial(ctx context.Context, reason string) context.Context

WithNoDial constructs a new context with an option that instructs the network to not attempt a new dial when opening a stream.

func WithSimultaneousConnect

func WithSimultaneousConnect(ctx context.Context, isClient bool, reason string) context.Context

WithSimultaneousConnect constructs a new context with an option that instructs the transport to apply hole punching logic where applicable. EXPERIMENTAL

func WithUseTransient deprecated

func WithUseTransient(ctx context.Context, reason string) context.Context

WithUseTransient constructs a new context with an option that instructs the network that it is acceptable to use a transient connection when opening a new stream.

Deprecated: Use WithAllowLimitedConn instead.

Types

type AddrDelay added in v0.28.0

type AddrDelay struct {
	Addr  ma.Multiaddr
	Delay time.Duration
}

AddrDelay provides an address along with the delay after which the address should be dialed

type Conn

type Conn interface {
	io.Closer

	ConnSecurity
	ConnMultiaddrs
	ConnStat
	ConnScoper

	// ID returns an identifier that uniquely identifies this Conn within this
	// host, during this run. Connection IDs may repeat across restarts.
	ID() string

	// NewStream constructs a new Stream over this conn.
	NewStream(context.Context) (Stream, error)

	// GetStreams returns all open streams over this conn.
	GetStreams() []Stream

	// IsClosed returns whether a connection is fully closed, so it can
	// be garbage collected.
	IsClosed() bool
}

Conn is a connection to a remote peer. It multiplexes streams. Usually there is no need to use a Conn directly, but it may be useful to get information about the peer on the other side:

stream.Conn().RemotePeer()

type ConnManagementScope

type ConnManagementScope interface {
	ResourceScopeSpan

	// PeerScope returns the peer scope associated with this connection.
	// It returns nil if the connection is not yet associated with any peer.
	PeerScope() PeerScope

	// SetPeer sets the peer for a previously unassociated connection
	SetPeer(peer.ID) error
}

ConnManagementScope is the low level interface for connection resource scopes. This interface is used by the low level components of the system who create and own the span of a connection scope.

type ConnMultiaddrs

type ConnMultiaddrs interface {
	// LocalMultiaddr returns the local Multiaddr associated
	// with this connection
	LocalMultiaddr() ma.Multiaddr

	// RemoteMultiaddr returns the remote Multiaddr associated
	// with this connection
	RemoteMultiaddr() ma.Multiaddr
}

ConnMultiaddrs is an interface mixin for connection types that provide multiaddr addresses for the endpoints.

type ConnScope

type ConnScope interface {
	ResourceScope
}

ConnScope is the user view of a connection scope

type ConnScoper

type ConnScoper interface {
	// Scope returns the user view of this connection's resource scope
	Scope() ConnScope
}

ConnScoper is the interface that one can mix into a connection interface to give it a resource management scope

type ConnSecurity

type ConnSecurity interface {
	// LocalPeer returns our peer ID
	LocalPeer() peer.ID

	// RemotePeer returns the peer ID of the remote peer.
	RemotePeer() peer.ID

	// RemotePublicKey returns the public key of the remote peer.
	RemotePublicKey() ic.PubKey

	// ConnState returns information about the connection state.
	ConnState() ConnectionState
}

ConnSecurity is the interface that one can mix into a connection interface to give it the security methods.

type ConnStat

type ConnStat interface {
	// Stat stores metadata pertaining to this conn.
	Stat() ConnStats
}

ConnStat is an interface mixin for connection types that provide connection statistics.

type ConnStats

type ConnStats struct {
	Stats
	// NumStreams is the number of streams on the connection.
	NumStreams int
}

ConnStats stores metadata pertaining to a given Conn.

type Connectedness

type Connectedness int

Connectedness signals the capacity for a connection with a given node. It is used to signal to services and other peers whether a node is reachable.

const (
	// NotConnected means no connection to peer, and no extra information (default)
	NotConnected Connectedness = iota

	// Connected means has an open, live connection to peer
	Connected

	// Deprecated: CanConnect is deprecated and will be removed in a future release.
	//
	// CanConnect means recently connected to peer, terminated gracefully
	CanConnect

	// Deprecated: CannotConnect is deprecated and will be removed in a future release.
	//
	// CannotConnect means recently attempted connecting but failed to connect.
	// (should signal "made effort, failed")
	CannotConnect

	// Limited means we have a transient connection to the peer, but aren't fully connected.
	Limited
)

func (Connectedness) String

func (c Connectedness) String() string

type ConnectionState added in v0.24.0

type ConnectionState struct {
	// The stream multiplexer used on this connection (if any). For example: /yamux/1.0.0
	StreamMultiplexer protocol.ID
	// The security protocol used on this connection (if any). For example: /tls/1.0.0
	Security protocol.ID
	// the transport used on this connection. For example: tcp
	Transport string
	// indicates whether StreamMultiplexer was selected using inlined muxer negotiation
	UsedEarlyMuxerNegotiation bool
}

ConnectionState holds information about the connection.

type DialRanker added in v0.28.0

type DialRanker func([]ma.Multiaddr) []AddrDelay

DialRanker provides a schedule of dialing the provided addresses

type Dialer

type Dialer interface {
	// Peerstore returns the internal peerstore
	// This is useful to tell the dialer about a new address for a peer.
	// Or use one of the public keys found out over the network.
	Peerstore() peerstore.Peerstore

	// LocalPeer returns the local peer associated with this network
	LocalPeer() peer.ID

	// DialPeer establishes a connection to a given peer
	DialPeer(context.Context, peer.ID) (Conn, error)

	// ClosePeer closes the connection to a given peer
	ClosePeer(peer.ID) error

	// Connectedness returns a state signaling connection capabilities
	Connectedness(peer.ID) Connectedness

	// Peers returns the peers connected
	Peers() []peer.ID

	// Conns returns the connections in this Network
	Conns() []Conn

	// ConnsToPeer returns the connections in this Network for given peer.
	ConnsToPeer(p peer.ID) []Conn

	// Notify/StopNotify register and unregister a notifiee for signals
	Notify(Notifiee)
	StopNotify(Notifiee)

	// CanDial returns whether the dialer can dial peer p at addr
	CanDial(p peer.ID, addr ma.Multiaddr) bool
}

Dialer represents a service that can dial out to peers (this is usually just a Network, but other services may not need the whole stack, and thus it becomes easier to mock)

type Direction

type Direction int

Direction represents which peer in a stream initiated a connection.

const (
	// DirUnknown is the default direction.
	DirUnknown Direction = iota
	// DirInbound is for when the remote peer initiated a connection.
	DirInbound
	// DirOutbound is for when the local peer initiated a connection.
	DirOutbound
)

func (Direction) String

func (d Direction) String() string

type MultiaddrDNSResolver added in v0.37.0

type MultiaddrDNSResolver interface {
	// ResolveDNSAddr resolves the first /dnsaddr component in a multiaddr.
	// Recurisvely resolves DNSADDRs up to the recursion limit
	ResolveDNSAddr(ctx context.Context, expectedPeerID peer.ID, maddr ma.Multiaddr, recursionLimit, outputLimit int) ([]ma.Multiaddr, error)
	// ResolveDNSComponent resolves the first /{dns,dns4,dns6} component in a multiaddr.
	ResolveDNSComponent(ctx context.Context, maddr ma.Multiaddr, outputLimit int) ([]ma.Multiaddr, error)
}

type Multiplexer

type Multiplexer interface {
	// NewConn constructs a new connection
	NewConn(c net.Conn, isServer bool, scope PeerScope) (MuxedConn, error)
}

Multiplexer wraps a net.Conn with a stream multiplexing implementation and returns a MuxedConn that supports opening multiple streams over the underlying net.Conn

type MuxedConn

type MuxedConn interface {
	// Close closes the stream muxer and the the underlying net.Conn.
	io.Closer

	// IsClosed returns whether a connection is fully closed, so it can
	// be garbage collected.
	IsClosed() bool

	// OpenStream creates a new stream.
	OpenStream(context.Context) (MuxedStream, error)

	// AcceptStream accepts a stream opened by the other side.
	AcceptStream() (MuxedStream, error)
}

MuxedConn represents a connection to a remote peer that has been extended to support stream multiplexing.

A MuxedConn allows a single net.Conn connection to carry many logically independent bidirectional streams of binary data.

Together with network.ConnSecurity, MuxedConn is a component of the transport.CapableConn interface, which represents a "raw" network connection that has been "upgraded" to support the libp2p capabilities of secure communication and stream multiplexing.

type MuxedStream

type MuxedStream interface {
	io.Reader
	io.Writer

	// Close closes the stream.
	//
	// * Any buffered data for writing will be flushed.
	// * Future reads will fail.
	// * Any in-progress reads/writes will be interrupted.
	//
	// Close may be asynchronous and _does not_ guarantee receipt of the
	// data.
	//
	// Close closes the stream for both reading and writing.
	// Close is equivalent to calling `CloseRead` and `CloseWrite`. Importantly, Close will not wait for any form of acknowledgment.
	// If acknowledgment is required, the caller must call `CloseWrite`, then wait on the stream for a response (or an EOF),
	// then call Close() to free the stream object.
	//
	// When done with a stream, the user must call either Close() or `Reset()` to discard the stream, even after calling `CloseRead` and/or `CloseWrite`.
	io.Closer

	// CloseWrite closes the stream for writing but leaves it open for
	// reading.
	//
	// CloseWrite does not free the stream, users must still call Close or
	// Reset.
	CloseWrite() error

	// CloseRead closes the stream for reading but leaves it open for
	// writing.
	//
	// When CloseRead is called, all in-progress Read calls are interrupted with a non-EOF error and
	// no further calls to Read will succeed.
	//
	// The handling of new incoming data on the stream after calling this function is implementation defined.
	//
	// CloseRead does not free the stream, users must still call Close or
	// Reset.
	CloseRead() error

	// Reset closes both ends of the stream. Use this to tell the remote
	// side to hang up and go away.
	Reset() error

	SetDeadline(time.Time) error
	SetReadDeadline(time.Time) error
	SetWriteDeadline(time.Time) error
}

MuxedStream is a bidirectional io pipe within a connection.

type NATDeviceType

type NATDeviceType int

NATDeviceType indicates the type of the NAT device.

const (
	// NATDeviceTypeUnknown indicates that the type of the NAT device is unknown.
	NATDeviceTypeUnknown NATDeviceType = iota

	// NATDeviceTypeCone indicates that the NAT device is a Cone NAT.
	// A Cone NAT is a NAT where all outgoing connections from the same source IP address and port are mapped by the NAT device
	// to the same IP address and port irrespective of the destination address.
	// With regards to RFC 3489, this could be either a Full Cone NAT, a Restricted Cone NAT or a
	// Port Restricted Cone NAT. However, we do NOT differentiate between them here and simply classify all such NATs as a Cone NAT.
	// NAT traversal with hole punching is possible with a Cone NAT ONLY if the remote peer is ALSO behind a Cone NAT.
	// If the remote peer is behind a Symmetric NAT, hole punching will fail.
	NATDeviceTypeCone

	// NATDeviceTypeSymmetric indicates that the NAT device is a Symmetric NAT.
	// A Symmetric NAT maps outgoing connections with different destination addresses to different IP addresses and ports,
	// even if they originate from the same source IP address and port.
	// NAT traversal with hole-punching is currently NOT possible in libp2p with Symmetric NATs irrespective of the remote peer's NAT type.
	NATDeviceTypeSymmetric
)

func (NATDeviceType) String

func (r NATDeviceType) String() string

type NATTransportProtocol

type NATTransportProtocol int

NATTransportProtocol is the transport protocol for which the NAT Device Type has been determined.

const (
	// NATTransportUDP means that the NAT Device Type has been determined for the UDP Protocol.
	NATTransportUDP NATTransportProtocol = iota
	// NATTransportTCP means that the NAT Device Type has been determined for the TCP Protocol.
	NATTransportTCP
)

func (NATTransportProtocol) String

func (n NATTransportProtocol) String() string

type Network

type Network interface {
	Dialer
	io.Closer

	// SetStreamHandler sets the handler for new streams opened by the
	// remote side. This operation is thread-safe.
	SetStreamHandler(StreamHandler)

	// NewStream returns a new stream to given peer p.
	// If there is no connection to p, attempts to create one.
	NewStream(context.Context, peer.ID) (Stream, error)

	// Listen tells the network to start listening on given multiaddrs.
	Listen(...ma.Multiaddr) error

	// ListenAddresses returns a list of addresses at which this network listens.
	ListenAddresses() []ma.Multiaddr

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

	// ResourceManager returns the ResourceManager associated with this network
	ResourceManager() ResourceManager
}

Network is the interface used to connect to the outside world. It dials and listens for connections. it uses a Swarm to pool connections (see swarm pkg, and peerstream.Swarm). Connections are encrypted with a TLS-like protocol.

type NoopNotifiee

type NoopNotifiee struct{}

func (*NoopNotifiee) Connected

func (nn *NoopNotifiee) Connected(n Network, c Conn)

func (*NoopNotifiee) Disconnected

func (nn *NoopNotifiee) Disconnected(n Network, c Conn)

func (*NoopNotifiee) Listen

func (nn *NoopNotifiee) Listen(n Network, addr ma.Multiaddr)

func (*NoopNotifiee) ListenClose

func (nn *NoopNotifiee) ListenClose(n Network, addr ma.Multiaddr)

type Notifiee

type Notifiee interface {
	Listen(Network, ma.Multiaddr)      // called when network starts listening on an addr
	ListenClose(Network, ma.Multiaddr) // called when network stops listening on an addr
	Connected(Network, Conn)           // called when a connection opened
	Disconnected(Network, Conn)        // called when a connection closed
}

Notifiee is an interface for an object wishing to receive notifications from a Network.

type NotifyBundle

type NotifyBundle struct {
	ListenF      func(Network, ma.Multiaddr)
	ListenCloseF func(Network, ma.Multiaddr)

	ConnectedF    func(Network, Conn)
	DisconnectedF func(Network, Conn)
}

NotifyBundle implements Notifiee by calling any of the functions set on it, and nop'ing if they are unset. This is the easy way to register for notifications.

func (*NotifyBundle) Connected

func (nb *NotifyBundle) Connected(n Network, c Conn)

Connected calls ConnectedF if it is not null.

func (*NotifyBundle) Disconnected

func (nb *NotifyBundle) Disconnected(n Network, c Conn)

Disconnected calls DisconnectedF if it is not null.

func (*NotifyBundle) Listen

func (nb *NotifyBundle) Listen(n Network, a ma.Multiaddr)

Listen calls ListenF if it is not null.

func (*NotifyBundle) ListenClose

func (nb *NotifyBundle) ListenClose(n Network, a ma.Multiaddr)

ListenClose calls ListenCloseF if it is not null.

type NullResourceManager

type NullResourceManager struct{}

NullResourceManager is a stub for tests and initialization of default values

func (*NullResourceManager) Close added in v0.24.0

func (n *NullResourceManager) Close() error

func (*NullResourceManager) OpenConnection added in v0.24.0

func (n *NullResourceManager) OpenConnection(dir Direction, usefd bool, endpoint multiaddr.Multiaddr) (ConnManagementScope, error)

func (*NullResourceManager) OpenStream added in v0.24.0

func (*NullResourceManager) ViewPeer added in v0.24.0

func (n *NullResourceManager) ViewPeer(p peer.ID, f func(PeerScope) error) error

func (*NullResourceManager) ViewProtocol added in v0.24.0

func (n *NullResourceManager) ViewProtocol(p protocol.ID, f func(ProtocolScope) error) error

func (*NullResourceManager) ViewService added in v0.24.0

func (n *NullResourceManager) ViewService(svc string, f func(ServiceScope) error) error

func (*NullResourceManager) ViewSystem added in v0.24.0

func (n *NullResourceManager) ViewSystem(f func(ResourceScope) error) error

func (*NullResourceManager) ViewTransient added in v0.24.0

func (n *NullResourceManager) ViewTransient(f func(ResourceScope) error) error

type NullScope

type NullScope struct{}

NullScope is a stub for tests and initialization of default values

func (*NullScope) BeginSpan added in v0.24.0

func (n *NullScope) BeginSpan() (ResourceScopeSpan, error)

func (*NullScope) Done added in v0.24.0

func (n *NullScope) Done()

func (*NullScope) Name added in v0.24.0

func (n *NullScope) Name() string

func (*NullScope) Peer added in v0.24.0

func (n *NullScope) Peer() peer.ID

func (*NullScope) PeerScope added in v0.24.0

func (n *NullScope) PeerScope() PeerScope

func (*NullScope) Protocol added in v0.24.0

func (n *NullScope) Protocol() protocol.ID

func (*NullScope) ProtocolScope added in v0.24.0

func (n *NullScope) ProtocolScope() ProtocolScope

func (*NullScope) ReleaseMemory added in v0.24.0

func (n *NullScope) ReleaseMemory(size int)

func (*NullScope) ReserveMemory added in v0.24.0

func (n *NullScope) ReserveMemory(size int, prio uint8) error

func (*NullScope) ServiceScope added in v0.24.0

func (n *NullScope) ServiceScope() ServiceScope

func (*NullScope) SetPeer added in v0.24.0

func (n *NullScope) SetPeer(peer.ID) error

func (*NullScope) SetProtocol added in v0.24.0

func (n *NullScope) SetProtocol(proto protocol.ID) error

func (*NullScope) SetService added in v0.24.0

func (n *NullScope) SetService(srv string) error

func (*NullScope) Stat added in v0.24.0

func (n *NullScope) Stat() ScopeStat

type PeerScope

type PeerScope interface {
	ResourceScope

	// Peer returns the peer ID for this scope
	Peer() peer.ID
}

PeerScope is the interface for peer resource scopes.

type ProtocolScope

type ProtocolScope interface {
	ResourceScope

	// Protocol returns the protocol for this scope
	Protocol() protocol.ID
}

ProtocolScope is the interface for protocol resource scopes.

type Reachability

type Reachability int

Reachability indicates how reachable a node is.

const (
	// ReachabilityUnknown indicates that the reachability status of the
	// node is unknown.
	ReachabilityUnknown Reachability = iota

	// ReachabilityPublic indicates that the node is reachable from the
	// public internet.
	ReachabilityPublic

	// ReachabilityPrivate indicates that the node is not reachable from the
	// public internet.
	//
	// NOTE: This node may _still_ be reachable via relays.
	ReachabilityPrivate
)

func (Reachability) String

func (r Reachability) String() string

type ResourceManager

type ResourceManager interface {
	ResourceScopeViewer

	// OpenConnection creates a new connection scope not yet associated with any peer; the connection
	// is scoped at the transient scope.
	// The caller owns the returned scope and is responsible for calling Done in order to signify
	// the end of the scope's span.
	OpenConnection(dir Direction, usefd bool, endpoint multiaddr.Multiaddr) (ConnManagementScope, error)

	// OpenStream creates a new stream scope, initially unnegotiated.
	// An unnegotiated stream will be initially unattached to any protocol scope
	// and constrained by the transient scope.
	// The caller owns the returned scope and is responsible for calling Done in order to signify
	// the end of th scope's span.
	OpenStream(p peer.ID, dir Direction) (StreamManagementScope, error)

	// Close closes the resource manager
	Close() error
}

ResourceManager is the interface to the network resource management subsystem. The ResourceManager tracks and accounts for resource usage in the stack, from the internals to the application, and provides a mechanism to limit resource usage according to a user configurable policy.

Resource Management through the ResourceManager is based on the concept of Resource Management Scopes, whereby resource usage is constrained by a DAG of scopes, The following diagram illustrates the structure of the resource constraint DAG: System

+------------> Transient.............+................+
|                                    .                .
+------------>  Service------------- . ----------+    .
|                                    .           |    .
+------------->  Protocol----------- . ----------+    .
|                                    .           |    .
+-------------->  Peer               \           |    .
                   +------------> Connection     |    .
                   |                             \    \
                   +--------------------------->  Stream

The basic resources accounted by the ResourceManager include memory, streams, connections, and file descriptors. These account for both space and time used by the stack, as each resource has a direct effect on the system availability and performance.

The modus operandi of the resource manager is to restrict resource usage at the time of reservation. When a component of the stack needs to use a resource, it reserves it in the appropriate scope. The resource manager gates the reservation against the scope applicable limits; if the limit is exceeded, then an error (wrapping ErrResourceLimitExceeded) and it is up the component to act accordingly. At the lower levels of the stack, this will normally signal a failure of some sorts, like failing to opening a stream or a connection, which will propagate to the programmer. Some components may be able to handle resource reservation failure more gracefully; for instance a muxer trying to grow a buffer for a window change, will simply retain the existing window size and continue to operate normally albeit with some degraded throughput. All resources reserved in some scope are released when the scope is closed. For low level scopes, mainly Connection and Stream scopes, this happens when the connection or stream is closed.

Service programmers will typically use the resource manager to reserve memory for their subsystem. This happens with two avenues: the programmer can attach a stream to a service, whereby resources reserved by the stream are automatically accounted in the service budget; or the programmer may directly interact with the service scope, by using ViewService through the resource manager interface.

Application programmers can also directly reserve memory in some applicable scope. In order to facilitate control flow delimited resource accounting, all scopes defined in the system allow for the user to create spans. Spans are temporary scopes rooted at some other scope and release their resources when the programmer is done with them. Span scopes can form trees, with nested spans.

Typical Usage:

  • Low level components of the system (transports, muxers) all have access to the resource manager and create connection and stream scopes through it. These scopes are accessible to the user, albeit with a narrower interface, through Conn and Stream objects who have a Scope method.
  • Services typically center around streams, where the programmer can attach streams to a particular service. They can also directly reserve memory for a service by accessing the service scope using the ResourceManager interface.
  • Applications that want to account for their network resource usage can reserve memory, typically using a span, directly in the System or a Service scope; they can also opt to use appropriate stream scopes for streams that they create or own.

User Serviceable Parts: the user has the option to specify their own implementation of the interface. We provide a canonical implementation in the go-libp2p-resource-manager package. The user of that package can specify limits for the various scopes, which can be static or dynamic.

WARNING The ResourceManager interface is considered experimental and subject to change in subsequent releases.

type ResourceScope

type ResourceScope interface {
	// ReserveMemory reserves memory/buffer space in the scope; the unit is bytes.
	//
	// If ReserveMemory returns an error, then no memory was reserved and the caller should handle
	// the failure condition.
	//
	// The priority argument indicates the priority of the memory reservation. A reservation
	// will fail if the available memory is less than (1+prio)/256 of the scope limit, providing
	// a mechanism to gracefully handle optional reservations that might overload the system.
	// For instance, a muxer growing a window buffer will use a low priority and only grow the buffer
	// if there is no memory pressure in the system.
	//
	// There are 4 predefined priority levels, Low, Medium, High and Always,
	// capturing common patterns, but the user is free to use any granularity applicable to his case.
	ReserveMemory(size int, prio uint8) error

	// ReleaseMemory explicitly releases memory previously reserved with ReserveMemory
	ReleaseMemory(size int)

	// Stat retrieves current resource usage for the scope.
	Stat() ScopeStat

	// BeginSpan creates a new span scope rooted at this scope
	BeginSpan() (ResourceScopeSpan, error)
}

ResourceScope is the interface for all scopes.

type ResourceScopeSpan

type ResourceScopeSpan interface {
	ResourceScope
	// Done ends the span and releases associated resources.
	Done()
}

ResourceScopeSpan is a ResourceScope with a delimited span. Span scopes are control flow delimited and release all their associated resources when the programmer calls Done.

Example:

s, err := someScope.BeginSpan()
if err != nil { ... }
defer s.Done()

if err := s.ReserveMemory(...); err != nil { ... }
// ... use memory

type ResourceScopeViewer

type ResourceScopeViewer interface {
	// ViewSystem views the system-wide resource scope.
	// The system scope is the top level scope that accounts for global
	// resource usage at all levels of the system. This scope constrains all
	// other scopes and institutes global hard limits.
	ViewSystem(func(ResourceScope) error) error

	// ViewTransient views the transient (DMZ) resource scope.
	// The transient scope accounts for resources that are in the process of
	// full establishment. For instance, a new connection prior to the
	// handshake does not belong to any peer, but it still needs to be
	// constrained as this opens an avenue for attacks in transient resource
	// usage. Similarly, a stream that has not negotiated a protocol yet is
	// constrained by the transient scope.
	ViewTransient(func(ResourceScope) error) error

	// ViewService retrieves a service-specific scope.
	ViewService(string, func(ServiceScope) error) error

	// ViewProtocol views the resource management scope for a specific protocol.
	ViewProtocol(protocol.ID, func(ProtocolScope) error) error

	// ViewPeer views the resource management scope for a specific peer.
	ViewPeer(peer.ID, func(PeerScope) error) error
}

ResourceScopeViewer is a mixin interface providing view methods for accessing top level scopes.

type ScopeStat

type ScopeStat struct {
	NumStreamsInbound  int
	NumStreamsOutbound int
	NumConnsInbound    int
	NumConnsOutbound   int
	NumFD              int

	Memory int64
}

ScopeStat is a struct containing resource accounting information.

type ServiceScope

type ServiceScope interface {
	ResourceScope

	// Name returns the name of this service
	Name() string
}

ServiceScope is the interface for service resource scopes

type Stats

type Stats struct {
	// Direction specifies whether this is an inbound or an outbound connection.
	Direction Direction
	// Opened is the timestamp when this connection was opened.
	Opened time.Time
	// Limited indicates that this connection is Limited. It maybe limited by
	// bytes or time. In practice, this is a connection formed over a circuit v2
	// relay.
	Limited bool
	// Extra stores additional metadata about this connection.
	Extra map[interface{}]interface{}
}

Stats stores metadata pertaining to a given Stream / Conn.

type Stream

type Stream interface {
	MuxedStream

	// ID returns an identifier that uniquely identifies this Stream within this
	// host, during this run. Stream IDs may repeat across restarts.
	ID() string

	Protocol() protocol.ID
	SetProtocol(id protocol.ID) error

	// Stat returns metadata pertaining to this stream.
	Stat() Stats

	// Conn returns the connection this stream is part of.
	Conn() Conn

	// Scope returns the user's view of this stream's resource scope
	Scope() StreamScope
}

Stream represents a bidirectional channel between two agents in a libp2p network. "agent" is as granular as desired, potentially being a "request -> reply" pair, or whole protocols.

Streams are backed by a multiplexer underneath the hood.

type StreamHandler

type StreamHandler func(Stream)

StreamHandler is the type of function used to listen for streams opened by the remote side.

type StreamManagementScope

type StreamManagementScope interface {
	ResourceScopeSpan

	// ProtocolScope returns the protocol resource scope associated with this stream.
	// It returns nil if the stream is not associated with any protocol scope.
	ProtocolScope() ProtocolScope
	// SetProtocol sets the protocol for a previously unnegotiated stream
	SetProtocol(proto protocol.ID) error

	// ServiceScope returns the service owning the stream, if any.
	ServiceScope() ServiceScope
	// SetService sets the service owning this stream.
	SetService(srv string) error

	// PeerScope returns the peer resource scope associated with this stream.
	PeerScope() PeerScope
}

StreamManagementScope is the interface for stream resource scopes. This interface is used by the low level components of the system who create and own the span of a stream scope.

type StreamScope

type StreamScope interface {
	ResourceScope

	// SetService sets the service owning this stream.
	SetService(srv string) error
}

StreamScope is the user view of a StreamScope.

Directories

Path Synopsis
Package mocknetwork is a generated GoMock package.
Package mocknetwork is a generated GoMock package.

Jump to

Keyboard shortcuts

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