swarm

package module
v0.0.0-...-16dc8a2 Latest Latest
Warning

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

Go to latest
Published: Jan 4, 2025 License: MIT Imports: 35 Imported by: 0

README

go-libp2p-swarm

Coverage Status Travis CI

The libp2p swarm manages groups of connections to peers, and handles incoming and outgoing streams.

The libp2p swarm is the 'low level' interface for working with a given libp2p network. It gives you more fine grained control over various aspects of the system. Most applications don't need this level of access, so the Swarm is generally wrapped in a Host abstraction that provides a more friendly interface. See the host interface for more info on that.

Table of Contents

Install

make install

Usage

Creating a swarm

To construct a swarm, you'll be calling NewSwarm. That function looks like this:

swarm, err := NewSwarm(ctx, laddrs, pid, pstore, bwc)

It takes five items to fully construct a swarm, the first is a go context.Context. This controls the lifetime of the swarm, and all swarm processes have their lifespan derived from the given context. You can just use context.Background() if you're not concerned with that.

The next argument is an array of multiaddrs that the swarm will open up listeners for. Once started, the swarm will start accepting and handling incoming connections on every given address. This argument is optional, you can pass nil and the swarm will not listen for any incoming connections (but will still be able to dial out to other peers).

After that, you'll need to give the swarm an identity in the form of a peer.ID. If you're not wanting to enable secio (libp2p's transport layer encryption), then you can pick any string for this value. For example peer.ID("FooBar123") would work. Note that passing a random string ID will result in your node not being able to communicate with other peers that have correctly generated IDs. To see how to generate a proper ID, see the below section on "Identity Generation".

The fourth argument is a peerstore. This is essentially a database that the swarm will use to store peer IDs, addresses, public keys, protocol preferences and more. You can construct one by importing github.com/libp2p/go-libp2p-peerstore and calling peerstore.NewPeerstore().

The final argument is a bandwidth metrics collector, This is used to track incoming and outgoing bandwidth on connections managed by this swarm. It is optional, and passing nil will simply result in no metrics for connections being available.

Identity Generation

A proper libp2p identity is PKI based. We currently have support for RSA and ed25519 keys. To create a 'correct' ID, you'll need to either load or generate a new keypair. Here is an example of doing so:

import (
	"fmt"
	"crypto/rand"

	ci "github.com/libp2p/go-libp2p-crypto"
	pstore "github.com/libp2p/go-libp2p-peerstore"
	peer "github.com/libp2p/go-libp2p-peer"
)

func demo() {
	// First, select a source of entropy. We're using the stdlib's crypto reader here
	src := rand.Reader

	// Now create a 2048 bit RSA key using that
	priv, pub, err := ci.GenerateKeyPairWithReader(ci.RSA, 2048, src)
	if err != nil {
		panic(err) // oh no!
	}

	// Now that we have a keypair, lets create our identity from it
	pid, err := peer.IDFromPrivateKey(priv)
	if err != nil {
		panic(err)
	}

	// Woo! Identity acquired!
	fmt.Println("I am ", pid)

	// Now, for the purposes of building a swarm, lets add this all to a peerstore.
	ps := pstore.NewPeerstore()
	ps.AddPubKey(pid, pub)
	ps.AddPrivKey(pid, priv)

	// Once you've got all that, creating a basic swarm can be as easy as
	ctx := context.Background()
	swarm, err := NewSwarm(ctx, nil, pid, ps, nil)

	// viola! A functioning swarm!
}
Streams

The swarm is designed around using multiplexed streams to communicate with other peers. When working with a swarm, you will want to set a function to handle incoming streams from your peers:

swrm.SetStreamHandler(func(s inet.Stream) {
	defer s.Close()
	fmt.Println("Got a stream from: ", s.SwarmConn().RemotePeer())
	fmt.Fprintln(s, "Hello Friend!")
})

Tip: Always make sure to close streams when you're done with them.

Opening streams is also pretty simple:

s, err := swrm.NewStreamWithPeer(ctx, rpid)
if err != nil {
	panic(err)
}
defer s.Close()

io.Copy(os.Stdout, s) // pipe the stream to stdout

Just pass a context and the ID of the peer you want a stream to, and you'll get back a stream to read and write on.

Contribute

PRs are welcome!

Small note: If editing the Readme, please conform to the standard-readme specification.

License

MIT © Jeromy Johnson

Documentation

Overview

Package swarm implements a connection muxer with a pair of channels to synchronize all network communication.

Index

Constants

This section is empty.

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")

	// ErrDialFailed is returned when connecting to a peer has ultimately failed
	ErrDialFailed = errors.New("dial attempt failed")

	// ErrDialToSelf is returned if we attempt to dial our own peer
	ErrDialToSelf = errors.New("dial to self attempted")
)
View Source
var ConnSetupTimeout = time.Minute * 5
View Source
var DialTimeout = time.Second * 10

DialTimeout is the amount of time each dial attempt has. We can think about making this larger down the road, or putting more granular timeouts (i.e. within each subcomponent of Dial)

View Source
var PSTransport pst.Transport

PSTransport is the default peerstream transport that will be used by any libp2p swarms.

Functions

This section is empty.

Types

type Conn

type Conn ps.Conn

Conn is a simple wrapper around a ps.Conn that also exposes some of the methods from the underlying conn.Conn. There's **five** "layers" to each connection:

  • 0. the net.Conn - underlying net.Conn (TCP/UDP/UTP/etc)
  • 1. the manet.Conn - provides multiaddr friendly Conn
  • 2. the conn.Conn - provides Peer friendly Conn (inc Secure channel)
  • 3. the peerstream.Conn - provides peerstream / spdysptream happiness
  • 4. the Conn - abstracts everyting out, exposing only key parts of underlying layers

(I know, this is kinda crazy. it's more historical than a good design. though the layers do build up pieces of functionality. and they're all just io.RW :) )

func (*Conn) Close

func (c *Conn) Close() error

Close closes the underlying stream connection

func (*Conn) GetStreams

func (c *Conn) GetStreams() ([]inet.Stream, error)

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) LocalPrivateKey

func (c *Conn) LocalPrivateKey() ic.PrivKey

LocalPrivateKey is the public key of the peer on this side

func (*Conn) NewStream

func (c *Conn) NewStream() (inet.Stream, error)

NewStream returns a new Stream from this connection

func (*Conn) NewSwarmStream

func (c *Conn) NewSwarmStream() (*Stream, error)

NewSwarmStream returns a new Stream from this connection

func (*Conn) RawConn

func (c *Conn) RawConn() iconn.Conn

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) StreamConn

func (c *Conn) StreamConn() *ps.Conn

func (*Conn) String

func (c *Conn) String() string

type ConnHandler

type ConnHandler func(*Conn)

ConnHandler is called when new conns are opened from remote peers. See peerstream.ConnHandler

type DialFunc

type DialFunc func(context.Context, peer.ID) (*Conn, error)

type DialSync

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

func NewDialSync

func NewDialSync(dfn DialFunc) *DialSync

func (*DialSync) DialLock

func (ds *DialSync) DialLock(ctx context.Context, p peer.ID) (*Conn, error)

type Network

type Network Swarm

Network implements the inet.Network interface. It is simply a swarm, with a few different functions to implement inet.Network.

func NewNetwork

func NewNetwork(ctx context.Context, listen []ma.Multiaddr, local peer.ID,
	peers pstore.Peerstore, bwc metrics.Reporter) (*Network, error)

func NewNetworkWithProtector

func NewNetworkWithProtector(ctx context.Context, listen []ma.Multiaddr, local peer.ID,
	peers pstore.Peerstore, protec ipnet.Protector, bwc metrics.Reporter) (*Network, error)

NewNetwork constructs a new network and starts listening on given addresses.

func (*Network) Close

func (n *Network) Close() error

Close calls the ContextCloser func

func (*Network) ClosePeer

func (n *Network) ClosePeer(p peer.ID) error

ClosePeer connection to peer

func (*Network) Connectedness

func (n *Network) Connectedness(p peer.ID) inet.Connectedness

Connectedness returns a state signaling connection capabilities For now only returns Connected || NotConnected. Expand into more later.

func (*Network) Conns

func (n *Network) Conns() []inet.Conn

Conns returns the connected peers

func (*Network) ConnsToPeer

func (n *Network) ConnsToPeer(p peer.ID) []inet.Conn

ConnsToPeer returns the connections in this Netowrk for given peer.

func (*Network) DialPeer

func (n *Network) DialPeer(ctx context.Context, p peer.ID) (inet.Conn, error)

DialPeer attempts to establish a connection to a given peer. Respects the context.

func (*Network) InterfaceListenAddresses

func (n *Network) InterfaceListenAddresses() ([]ma.Multiaddr, error)

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.

func (*Network) Listen

func (n *Network) Listen(addrs ...ma.Multiaddr) error

Listen tells the network to start listening on given multiaddrs.

func (*Network) ListenAddresses

func (n *Network) ListenAddresses() []ma.Multiaddr

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

func (*Network) LocalPeer

func (n *Network) LocalPeer() peer.ID

LocalPeer the network's LocalPeer

func (*Network) NewStream

func (n *Network) NewStream(ctx context.Context, p peer.ID) (inet.Stream, error)

NewStream returns a new stream to given peer p. If there is no connection to p, attempts to create one.

func (*Network) Notify

func (n *Network) Notify(f inet.Notifiee)

Notify signs up Notifiee to receive signals when events happen

func (*Network) Peers

func (n *Network) Peers() []peer.ID

Peers returns the known peer IDs from the Peerstore

func (*Network) Peerstore

func (n *Network) Peerstore() pstore.Peerstore

Peerstore returns the Peerstore, which tracks known peers

func (*Network) Process

func (n *Network) Process() goprocess.Process

Process returns the network's Process

func (*Network) SetConnHandler

func (n *Network) SetConnHandler(h inet.ConnHandler)

SetConnHandler sets the conn handler on the Network. This operation is threadsafe.

func (*Network) SetStreamHandler

func (n *Network) SetStreamHandler(h inet.StreamHandler)

SetStreamHandler sets the protocol handler on the Network's Muxer. This operation is threadsafe.

func (*Network) StopNotify

func (n *Network) StopNotify(f inet.Notifiee)

StopNotify unregisters Notifiee fromr receiving signals

func (*Network) String

func (n *Network) String() string

String returns a string representation of Network.

func (*Network) Swarm

func (n *Network) Swarm() *Swarm

Swarm returns the network's peerstream.Swarm

type Stream

type Stream ps.Stream

Stream is a wrapper around a ps.Stream that exposes a way to get our Conn and Swarm (instead of just the ps.Conn and ps.Swarm)

func (*Stream) Close

func (s *Stream) Close() error

Close closes the stream, indicating this side is finished with the stream.

func (*Stream) Conn

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

Conn returns the Conn associated with this Stream, as an inet.Conn

func (*Stream) Protocol

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

func (*Stream) Read

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

Read reads bytes from a stream.

func (*Stream) SetDeadline

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

func (*Stream) SetProtocol

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

func (*Stream) SetReadDeadline

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

func (*Stream) SetWriteDeadline

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

func (*Stream) Stream

func (s *Stream) Stream() *ps.Stream

Stream returns the underlying peerstream.Stream

func (*Stream) SwarmConn

func (s *Stream) SwarmConn() *Conn

SwarmConn returns the Conn associated with this Stream, as a *Conn

func (*Stream) Write

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

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

type Swarm

type Swarm struct {

	// filters for addresses that shouldnt be dialed
	Filters *filter.Filters
	// 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.

Uses peerstream.Swarm

func NewBlankSwarm

func NewBlankSwarm(ctx context.Context, id peer.ID, privkey ci.PrivKey, pstpt pst.Transport) *Swarm

func NewSwarm

func NewSwarm(ctx context.Context, listenAddrs []ma.Multiaddr, local peer.ID,
	peers pstore.Peerstore, bwc metrics.Reporter) (*Swarm, error)

func NewSwarmWithProtector

func NewSwarmWithProtector(ctx context.Context, listenAddrs []ma.Multiaddr, local peer.ID,
	peers pstore.Peerstore, protec ipnet.Protector, tpt pst.Transport, bwc metrics.Reporter) (*Swarm, error)

NewSwarm constructs a Swarm, with a Chan.

func (*Swarm) AddAddrFilter

func (s *Swarm) AddAddrFilter(f string) error

AddAddrFilter adds a multiaddr filter to the set of filters the swarm will use to determine which addresses not to dial to.

func (*Swarm) AddListenAddr

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

func (*Swarm) AddTransport

func (s *Swarm) AddTransport(t transport.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

Close stops the Swarm.

func (*Swarm) CloseConnection

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

CloseConnection removes a given peer from swarm + closes the connection

func (*Swarm) Connections

func (s *Swarm) Connections() []*Conn

Connections returns a slice of all connections.

func (*Swarm) ConnectionsToPeer

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

ConnectionsToPeer returns all the live connections to p

func (*Swarm) Context

func (s *Swarm) Context() context.Context

Context returns the context of the swarm

func (*Swarm) Dial

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

Dial connects to a peer.

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 achive connection.

func (*Swarm) HaveConnsToPeer

func (s *Swarm) HaveConnsToPeer(p peer.ID) bool

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

func (*Swarm) ListenAddresses

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

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

func (*Swarm) LocalPeer

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

LocalPeer returns the local peer swarm is associated to.

func (*Swarm) NewStreamWithPeer

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

NewStreamWithPeer creates a new stream on any available connection to p

func (*Swarm) Notify

func (s *Swarm) Notify(f inet.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) Process

func (s *Swarm) Process() goprocess.Process

Process returns the Process of the swarm

func (*Swarm) SetConnHandler

func (s *Swarm) SetConnHandler(handler ConnHandler)

SetConnHandler assigns the handler for new connections. See peerstream. You will rarely use this. See SetStreamHandler

func (*Swarm) SetStreamHandler

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

SetStreamHandler assigns the handler for new streams. See peerstream.

func (*Swarm) StopNotify

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

StopNotify unregisters Notifiee fromr receiving signals

func (*Swarm) StreamSwarm

func (s *Swarm) StreamSwarm() *ps.Swarm

StreamSwarm returns the underlying peerstream.Swarm

Jump to

Keyboard shortcuts

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