p2p

package module
v0.0.0-...-d4b7e32 Latest Latest
Warning

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

Go to latest
Published: Aug 12, 2023 License: MPL-2.0 Imports: 7 Imported by: 21

README

P2P

A Library for writing Peer-to-Peer applications.

Many peer-to-peer libraries go to great lengths to provide a reliable stream abstraction over as many different transports as possible. That makes them unsuitable for modeling protocols over lossy mediums (UDP, IP, ethernet). This library takes a message oriented approach instead of a stream oriented approach.

Unreliable, fire-and-forget communication is provided using Tell and Receive methods. Reliable request-response communication is provided using Ask and ServeAsk methods.

The core abstraction is the Swarm. Which represents a group of nodes which can send messages to one another.

type Swarm[A Addr] interface {
    Tell(ctx context.Context, dst A, data []byte) error
    Receive(ctx context.Context, fn func(Message[A])) error

    ParseAddr(data []byte) (A, error)
    LocalAddrs() []A
    MTU(A) int
    Close() error
}

Addr is an interface type.

Overlay networks are a common pattern in p2p systems. Swarms have methods for introspection such as LocalAddrs and MTU. Addrs also have a canonical serialization provided by MarshalText and ParseAddr These two features make Swarms the building blocks for higher order swarms, which can be overlay networks. The underlying swarm is often referred to as the transport throughout these packages.

The power of the Swarm abstraction is exemplified by the fact we merely call some Swarms "transports" in certain contexts rather than having a separate Transport type, as other libraries do.

Swarms provide a Tell method, which makes a best effort to send the message payload to the destination. It will error if the message cannot be set in flight, but does not guarantee the transmision of the message if the error is nil.

Directory Organization

F is for Formats

Formats are just protocols that send/write once and receive/read many times.

  • x509 Deals with the formats in the x509 public key infrastructure.
S is for Swarm
  • In-Memory Swarm A swarm which transfers data to other swarms in memory. Useful for testing.

  • Multi Swarm Creates a multiplexed addressed space using names given to each subswarm. Applications can use this to "future-proof" their transport layer.

  • P2PKE Swarm A Secure Swarm which can secure any underlying Swarm.

  • QUIC Swarm A secure swarm supporting Asks built on the QUIC protocol. It can wrap any other p2p.Swarm, and provide a p2p.SecureAskSwarm

  • SSH Swarm A secure swarm supporting Asks built on the SSH protocol (TCP based).

  • UDP Swarm An insecure swarm, included mainly as a building block.

  • Fragmenting Swarm A higher order swarm which increases the MTU of an underlying swarm by breaking apart messages, and assembling them on the other side.

  • Virtual Swarm A swarm which can be used to mock swarms of any comparable address type, and any public key type.

The swarmutil package contains utilities for writing Swarms. The swarmtest package contains a test suite which checks that a given Swarm implementation exhibits all the behaviors expected.

P is for Protocols
  • Chord A package for the Chord DHT algorithm.

  • Kademlia A package for the Kademlia DHT algorithm.

  • Multiplexing Multiplexing creates multiple logical swarms on top of a single swarm. The p2pmux package provides string and integer multiplexers.

  • P2PKE P2PKE is an authenticated key exchange suitable for securing p2p.Swarms. Provides a session state machine, and a long-lived secure channel, which is used by s/p2pkeswarm

Test Utilities

The p2ptest packages contains utilities for testing, such as generating adjacency matricies for networks of various connectivities.

Documentation

Index

Constants

View Source
const (
	// PeerIDSize is the size of a PeerID in bytes
	PeerIDSize = 32
	// Base64Alphabet is used when encoding IDs as base64 strings.
	// It is a URL and filepath safe encoding, which maintains ordering.
	Base64Alphabet = "-0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "_" + "abcdefghijklmnopqrstuvwxyz"
)

Variables

View Source
var (
	ErrMTUExceeded       = errors.New("payload is larger than swarms MTU")
	ErrClosed            = net.ErrClosed
	ErrPublicKeyNotFound = fmt.Errorf("public key not found")
)

Functions

func CompareAddrs

func CompareAddrs(a, b Addr) int

func DiscardAsks

func DiscardAsks[A Addr](ctx context.Context, a AskServer[A]) error

func DiscardTells

func DiscardTells[A Addr](ctx context.Context, t Receiver[A]) error

func ExpandUnspecifiedIPs

func ExpandUnspecifiedIPs[A hasIP2[A]](xs []A) (ys []A)

ExpandUnspecifiedIPs will expand 0.0.0.0 into all of IPs on the host.

func ExtractIP

func ExtractIP(x Addr) (netip.Addr, bool)

func ExtractTCP

func ExtractTCP(x Addr) *net.TCPAddr

func ExtractUDP

func ExtractUDP(x Addr) *net.UDPAddr

func IsErrClosed

func IsErrClosed(err error) bool

func IsErrMTUExceeded

func IsErrMTUExceeded(err error) bool

func IsErrPublicKeyNotFound

func IsErrPublicKeyNotFound(err error) bool

func LookupPublicKeyInHandler

func LookupPublicKeyInHandler[A Addr, PublicKey any](s Secure[A, PublicKey], target A) PublicKey

LookupPublicKeyInHandler calls LookupPublicKey with an expired context, and panics on an error. SecureSwarms must be able to return a PublicKey retrieved from memory, during the execution of an AskHandler or TellHandler. to lookup a public key outside a handler, use the swarms LookupPublicKey method

func NoLinkLocal

func NoLinkLocal(x net.IP) bool

func NoLoopback

func NoLoopback(x net.IP) bool

func NoOpAskHandler

func NoOpAskHandler[A Addr](ctx context.Context, resp []byte, req Message[A]) int

func OnlyGlobal

func OnlyGlobal(x net.IP) bool

func Receive

func Receive[A Addr](ctx context.Context, t Receiver[A], m *Message[A]) error

Receive is convenience function which sets m to be a message received from t. m must be non-nil. m.Payload will be truncated (x = x[:0]), and then the message payload will be appended (x = append(x, payload...)) This is useful if the caller wants their own copy of the message, instead of borrowing the swarm's temporarily.

func VecBytes

func VecBytes(out []byte, v IOVec) []byte

VecBytes appends all the buffers in v to out and returns the result

func VecSize

func VecSize(v IOVec) int

VecSize returns the total size of the vector in bytes if it were contiguous. It is the sum of len(v[i]) for all i

Types

type Addr

type Addr interface {
	// MarshalText serializes the address in a way that can be unambiguously parsed by the Swarm
	// that produced this address.
	MarshalText() ([]byte, error)

	String() string
}

func FilterIPs

func FilterIPs(xs []Addr, preds ...func(netip.Addr) bool) (ys []Addr)

func MapIP

func MapIP(x Addr, fn func(netip.Addr) netip.Addr) Addr

func MapTCP

func MapTCP(x Addr, fn func(net.TCPAddr) net.TCPAddr) Addr

func MapUDP

func MapUDP(x Addr, fn func(net.UDPAddr) net.UDPAddr) Addr

type AddrParser

type AddrParser[A Addr] func([]byte) (A, error)

AddrParser is the type of functions which parse []byte into Addrs

type AskServer

type AskServer[A Addr] interface {
	// ServeAsk calls fn to serve a single ask request, it returns an error if anything went wrong.
	// Return values < 0 from fn will not result in an error returned from ServeAsk
	ServeAsk(ctx context.Context, ah func(ctx context.Context, resp []byte, req Message[A]) int) error
}

type AskSwarm

type AskSwarm[A Addr] interface {
	Swarm[A]
	Asker[A]
	AskServer[A]
}

func ComposeAskSwarm

func ComposeAskSwarm[A Addr](swarm Swarm[A], ask askBidi[A]) AskSwarm[A]

type Asker

type Asker[A Addr] interface {
	// Ask sends req to addr, and writes the response to resp.
	// The number of bytes written to resp is returned, or an error.
	// If resp is too short for the response: io.ErrShortBuffer is returned.
	Ask(ctx context.Context, resp []byte, addr A, req IOVec) (int, error)
}

type ComparableAddr

type ComparableAddr interface {
	Addr
	comparable
}

ComparableAddr is an Addr which also satisfies comparable

type Fingerprinter

type Fingerprinter[PublicKey any] func(PublicKey) PeerID

Fingerprinter is the type of functions which create PeerIDs from PublicKeys

type HasIP

type HasIP interface {
	GetIP() netip.Addr
	MapIP(func(netip.Addr) netip.Addr) Addr
}

type HasPeerID

type HasPeerID interface {
	Addr
	GetPeerID() PeerID
}

type HasTCP

type HasTCP interface {
	GetTCP() net.TCPAddr
	MapTCP(func(net.TCPAddr) net.TCPAddr) Addr
}

type HasUDP

type HasUDP interface {
	GetUDP() net.UDPAddr
	MapUDP(func(net.UDPAddr) net.UDPAddr) Addr
}

type IOVec

type IOVec = net.Buffers

type Message

type Message[A Addr] struct {
	Src, Dst A
	Payload  []byte
}

type PeerID

type PeerID [32]byte

PeerID is a identifier cryptographically related to a public key

func ExtractPeerID

func ExtractPeerID(x Addr) PeerID

func (PeerID) Base64String

func (pid PeerID) Base64String() string

func (PeerID) Compare

func (p PeerID) Compare(q PeerID) int

func (PeerID) IsZero

func (p PeerID) IsZero() bool

func (PeerID) Lt

func (p PeerID) Lt(q PeerID) bool

func (PeerID) MarshalText

func (pid PeerID) MarshalText() ([]byte, error)

func (PeerID) String

func (pid PeerID) String() string

func (*PeerID) UnmarshalText

func (pid *PeerID) UnmarshalText(data []byte) error

type Receiver

type Receiver[A Addr] interface {
	// Recv blocks until the context is cancelled or 1 message is recieved.
	// fn is called with the message, which may be used until fn returns.
	// None of the message's fields may be accessed outside of fn.
	// All of the message's fields may be modified inside fn. A message is only ever delivered to one place,
	// so the message will never be accessed concurrently or after the call to fn.
	Receive(ctx context.Context, fn func(Message[A])) error
}

type Secure

type Secure[A Addr, PublicKey any] interface {
	PublicKey() PublicKey
	LookupPublicKey(ctx context.Context, addr A) (PublicKey, error)
}

type SecureAskSwarm

type SecureAskSwarm[A Addr, PublicKey any] interface {
	Swarm[A]
	AskSwarm[A]
	Secure[A, PublicKey]
}

func ComposeSecureAskSwarm

func ComposeSecureAskSwarm[A Addr, Pub any](swarm Swarm[A], ask askBidi[A], sec Secure[A, Pub]) SecureAskSwarm[A, Pub]

type SecureSwarm

type SecureSwarm[A Addr, PublicKey any] interface {
	Swarm[A]
	Secure[A, PublicKey]
}

func ComposeSecureSwarm

func ComposeSecureSwarm[A Addr, Pub any](swarm Swarm[A], sec Secure[A, Pub]) SecureSwarm[A, Pub]

type Swarm

type Swarm[A Addr] interface {
	Teller[A]
	Receiver[A]

	// LocalAddrs returns all the addresses that can be used to contact this Swarm
	LocalAddrs() []A
	// MTU returns the maximum transmission unit for the Swarm.
	// This is the maxiumum size of messages incoming and outgoing.
	MTU() int
	// Close releases all resources held by the swarm.
	// It should be called when the swarm is no longer in use.
	Close() error
	// ParseAddr attempts to parse an address from data
	ParseAddr(data []byte) (A, error)
}

Swarm represents a single node's view of an address space for nodes. Nodes have their own position(s) or address(es) in the swarm. Nodes can send and receive messages to and from other nodes in the Swarm.

type Teller

type Teller[A Addr] interface {
	// Tell sends a message containing data to dst
	// Tell returns an error if the message cannot be set in flight.
	// A nil error does not guarentee delivery of the message.
	// None of the buffers in v will be modified, but v may be modified.
	// After the call to Tell, v must not be retained.
	Tell(ctx context.Context, dst A, v IOVec) error
}

type UnwrapAddr

type UnwrapAddr interface {
	Unwrap() Addr
	Map(func(Addr) Addr) Addr
}

Directories

Path Synopsis
cmd
f
x509
package x509 implements Public Key Infrastructure X.509 formats.
package x509 implements Public Key Infrastructure X.509 formats.
p
s
vswarm
package vswarm implements a virtual swarm which is capable of emulating other types of swarms.
package vswarm implements a virtual swarm which is capable of emulating other types of swarms.

Jump to

Keyboard shortcuts

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