connmgr

package
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Mar 20, 2024 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package connmgr provides connection tracking and management interfaces for dep2p.

The ConnManager interface exported from this package allows dep2p to enforce an upper bound on the total number of open connections. To avoid service disruptions, connections can be tagged with metadata and optionally "protected" to ensure that essential connections are not arbitrarily cut.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type BumpFn

type BumpFn func(value DecayingValue, delta int) (after int)

BumpFn applies a delta onto an existing score, and returns the new score.

Non-trivial bump functions include exponential boosting, moving averages, ceilings, etc.

func BumpOverwrite

func BumpOverwrite() BumpFn

BumpOverwrite replaces the current value of the tag with the incoming one.

func BumpSumBounded

func BumpSumBounded(min, max int) BumpFn

BumpSumBounded keeps summing the incoming score, keeping it within a [min, max] range.

func BumpSumUnbounded

func BumpSumUnbounded() BumpFn

BumpSumUnbounded adds the incoming value to the peer's score.

type ConnManager

type ConnManager interface {
	// TagPeer tags a peer with a string, associating a weight with the tag.
	TagPeer(peer.ID, string, int)

	// Untag removes the tagged value from the peer.
	UntagPeer(p peer.ID, tag string)

	// UpsertTag updates an existing tag or inserts a new one.
	//
	// The connection manager calls the upsert function supplying the current
	// value of the tag (or zero if inexistent). The return value is used as
	// the new value of the tag.
	UpsertTag(p peer.ID, tag string, upsert func(int) int)

	// GetTagInfo returns the metadata associated with the peer,
	// or nil if no metadata has been recorded for the peer.
	GetTagInfo(p peer.ID) *TagInfo

	// TrimOpenConns terminates open connections based on an implementation-defined
	// heuristic.
	TrimOpenConns(ctx context.Context)

	// Notifee returns an implementation that can be called back to inform of
	// opened and closed connections.
	Notifee() network.Notifiee

	// Protect protects a peer from having its connection(s) pruned.
	//
	// Tagging allows different parts of the system to manage protections without interfering with one another.
	//
	// Calls to Protect() with the same tag are idempotent. They are not refcounted, so after multiple calls
	// to Protect() with the same tag, a single Unprotect() call bearing the same tag will revoke the protection.
	Protect(id peer.ID, tag string)

	// Unprotect removes a protection that may have been placed on a peer, under the specified tag.
	//
	// The return value indicates whether the peer continues to be protected after this call, by way of a different tag.
	// See notes on Protect() for more info.
	Unprotect(id peer.ID, tag string) (protected bool)

	// IsProtected returns true if the peer is protected for some tag; if the tag is the empty string
	// then it will return true if the peer is protected for any tag
	IsProtected(id peer.ID, tag string) (protected bool)

	// CheckLimit will return an error if the connection manager's internal
	// connection limit exceeds the provided system limit.
	CheckLimit(l GetConnLimiter) error

	// Close closes the connection manager and stops background processes.
	Close() error
}

ConnManager tracks connections to peers, and allows consumers to associate metadata with each peer.

It enables connections to be trimmed based on implementation-defined heuristics. The ConnManager allows dep2p to enforce an upper bound on the total number of open connections.

ConnManagers supporting decaying tags implement Decayer. Use the SupportsDecay function to safely cast an instance to Decayer, if supported.

type ConnectionGater

type ConnectionGater interface {
	// InterceptPeerDial tests whether we're permitted to Dial the specified peer.
	//
	// This is called by the network.Network implementation when dialling a peer.
	InterceptPeerDial(p peer.ID) (allow bool)

	// InterceptAddrDial tests whether we're permitted to dial the specified
	// multiaddr for the given peer.
	//
	// This is called by the network.Network implementation after it has
	// resolved the peer's addrs, and prior to dialling each.
	InterceptAddrDial(peer.ID, ma.Multiaddr) (allow bool)

	// InterceptAccept tests whether an incipient inbound connection is allowed.
	//
	// This is called by the upgrader, or by the transport directly (e.g. QUIC,
	// Bluetooth), straight after it has accepted a connection from its socket.
	InterceptAccept(network.ConnMultiaddrs) (allow bool)

	// InterceptSecured tests whether a given connection, now authenticated,
	// is allowed.
	//
	// This is called by the upgrader, after it has performed the security
	// handshake, and before it negotiates the muxer, or by the directly by the
	// transport, at the exact same checkpoint.
	InterceptSecured(network.Direction, peer.ID, network.ConnMultiaddrs) (allow bool)

	// InterceptUpgraded tests whether a fully capable connection is allowed.
	//
	// At this point, the connection a multiplexer has been selected.
	// When rejecting a connection, the gater can return a DisconnectReason.
	// Refer to the godoc on the ConnectionGater type for more information.
	//
	// NOTE: the dep2p implementation currently IGNORES the disconnect reason.
	InterceptUpgraded(network.Conn) (allow bool, reason control.DisconnectReason)
}

ConnectionGater can be implemented by a type that supports active inbound or outbound connection gating.

ConnectionGaters are active, whereas ConnManagers tend to be passive.

A ConnectionGater will be consulted during different states in the lifecycle of a connection being established/upgraded. Specific functions will be called throughout the process, to allow you to intercept the connection at that stage.

InterceptPeerDial is called on an imminent outbound peer dial request, prior
to the addresses of that peer being available/resolved. Blocking connections
at this stage is typical for blacklisting scenarios.

InterceptAddrDial is called on an imminent outbound dial to a peer on a
particular address. Blocking connections at this stage is typical for
address filtering.

InterceptAccept is called as soon as a transport listener receives an
inbound connection request, before any upgrade takes place. Transports who
accept already secure and/or multiplexed connections (e.g. possibly QUIC)
MUST call this method regardless, for correctness/consistency.

InterceptSecured is called for both inbound and outbound connections,
after a security handshake has taken place and we've authenticated the peer.

InterceptUpgraded is called for inbound and outbound connections, after
dep2p has finished upgrading the connection entirely to a secure,
multiplexed channel.

This interface can be used to implement *strict/active* connection management policies, such as hard limiting of connections once a maximum count has been reached, maintaining a peer blacklist, or limiting connections by transport quotas.

EXPERIMENTAL: a DISCONNECT protocol/message will be supported in the future. This allows gaters and other components to communicate the intention behind a connection closure, to curtail potential reconnection attempts.

For now, InterceptUpgraded can return a non-zero DisconnectReason when blocking a connection, but this interface is likely to change in the future as we solidify this feature. The reason why only this method can handle DisconnectReasons is that we require stream multiplexing capability to open a control protocol stream to transmit the message.

type DecayFn

type DecayFn func(value DecayingValue) (after int, rm bool)

DecayFn applies a decay to the peer's score. The implementation must call DecayFn at the interval supplied when registering the tag.

It receives a copy of the decaying value, and returns the score after applying the decay, as well as a flag to signal if the tag should be erased.

func DecayExpireWhenInactive

func DecayExpireWhenInactive(after time.Duration) DecayFn

DecayExpireWhenInactive expires a tag after a certain period of no bumps.

func DecayFixed

func DecayFixed(minuend int) DecayFn

DecayFixed subtracts from by the provided minuend, and deletes the tag when first reaching 0 or negative.

func DecayLinear

func DecayLinear(coef float64) DecayFn

DecayLinear applies a fractional coefficient to the value of the current tag, rounding down via math.Floor. It erases the tag when the result is zero.

func DecayNone

func DecayNone() DecayFn

DecayNone applies no decay.

type Decayer

type Decayer interface {
	io.Closer

	// RegisterDecayingTag creates and registers a new decaying tag, if and only
	// if a tag with the supplied name doesn't exist yet. Otherwise, an error is
	// returned.
	//
	// The caller provides the interval at which the tag is refreshed, as well
	// as the decay function and the bump function. Refer to godocs on DecayFn
	// and BumpFn for more info.
	RegisterDecayingTag(name string, interval time.Duration, decayFn DecayFn, bumpFn BumpFn) (DecayingTag, error)
}

Decayer is implemented by connection managers supporting decaying tags. A decaying tag is one whose value automatically decays over time.

The actual application of the decay behaviour is encapsulated in a user-provided decaying function (DecayFn). The function is called on every tick (determined by the interval parameter), and returns either the new value of the tag, or whether it should be erased altogether.

We do not set values on a decaying tag. Rather, we "bump" decaying tags by a delta. This calls the BumpFn with the old value and the delta, to determine the new value.

Such a pluggable design affords a great deal of flexibility and versatility. Behaviours that are straightforward to implement include:

  • Decay a tag by -1, or by half its current value, on every tick.
  • Every time a value is bumped, sum it to its current value.
  • Exponentially boost a score with every bump.
  • Sum the incoming score, but keep it within min, max bounds.

Commonly used DecayFns and BumpFns are provided in this package.

func SupportsDecay

func SupportsDecay(mgr ConnManager) (Decayer, bool)

SupportsDecay evaluates if the provided ConnManager supports decay, and if so, it returns the Decayer object. Refer to godocs on Decayer for more info.

type DecayingTag

type DecayingTag interface {
	// Name returns the name of the tag.
	Name() string

	// Interval is the effective interval at which this tag will tick. Upon
	// registration, the desired interval may be overwritten depending on the
	// decayer's resolution, and this method allows you to obtain the effective
	// interval.
	Interval() time.Duration

	// Bump applies a delta to a tag value, calling its bump function. The bump
	// will be applied asynchronously, and a non-nil error indicates a fault
	// when queuing.
	Bump(peer peer.ID, delta int) error

	// Remove removes a decaying tag from a peer. The removal will be applied
	// asynchronously, and a non-nil error indicates a fault when queuing.
	Remove(peer peer.ID) error

	// Close closes a decaying tag. The Decayer will stop tracking this tag,
	// and the state of all peers in the Connection Manager holding this tag
	// will be updated.
	//
	// The deletion is performed asynchronously.
	//
	// Once deleted, a tag should not be used, and further calls to Bump/Remove
	// will error.
	//
	// Duplicate calls to Remove will not return errors, but a failure to queue
	// the first actual removal, will (e.g. when the system is backlogged).
	Close() error
}

DecayingTag represents a decaying tag. The tag is a long-lived general object, used to operate on tag values for peers.

type DecayingValue

type DecayingValue struct {
	// Tag points to the tag this value belongs to.
	Tag DecayingTag

	// Peer is the peer ID to whom this value is associated.
	Peer peer.ID

	// Added is the timestamp when this value was added for the first time for
	// a tag and a peer.
	Added time.Time

	// LastVisit is the timestamp of the last visit.
	LastVisit time.Time

	// Value is the current value of the tag.
	Value int
}

DecayingValue represents a value for a decaying tag.

type GetConnLimiter

type GetConnLimiter interface {
	// GetConnLimit returns the total connection limit of the implementing component.
	GetConnLimit() int
}

GetConnLimiter provides access to a component's total connection limit.

type NullConnMgr

type NullConnMgr struct{}

NullConnMgr is a ConnMgr that provides no functionality.

func (NullConnMgr) CheckLimit

func (NullConnMgr) CheckLimit(l GetConnLimiter) error

func (NullConnMgr) Close

func (NullConnMgr) Close() error

func (NullConnMgr) GetTagInfo

func (NullConnMgr) GetTagInfo(peer.ID) *TagInfo

func (NullConnMgr) IsProtected

func (NullConnMgr) IsProtected(peer.ID, string) bool

func (NullConnMgr) Notifee

func (NullConnMgr) Notifee() network.Notifiee

func (NullConnMgr) Protect

func (NullConnMgr) Protect(peer.ID, string)

func (NullConnMgr) TagPeer

func (NullConnMgr) TagPeer(peer.ID, string, int)

func (NullConnMgr) TrimOpenConns

func (NullConnMgr) TrimOpenConns(ctx context.Context)

func (NullConnMgr) Unprotect

func (NullConnMgr) Unprotect(peer.ID, string) bool

func (NullConnMgr) UntagPeer

func (NullConnMgr) UntagPeer(peer.ID, string)

func (NullConnMgr) UpsertTag

func (NullConnMgr) UpsertTag(peer.ID, string, func(int) int)

type TagInfo

type TagInfo struct {
	FirstSeen time.Time
	Value     int

	// Tags maps tag ids to the numerical values.
	Tags map[string]int

	// Conns maps connection ids (such as remote multiaddr) to their creation time.
	Conns map[string]time.Time
}

TagInfo stores metadata associated with a peer.

Jump to

Keyboard shortcuts

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