Help us shape the future of Go! Take the 2026 Go Developer Survey

msngr

package module
v0.2.2 Latest Latest
Warning

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

Go to latest
Published: Mar 24, 2025 License: Apache-2.0 Imports: 13 Imported by: 1

README

Messenger

build-img pkg-img reportcard-img coverage-img

Messenger provides a simple arbitrary message sending API to multiple peers for libp2p-based protocols. The main purpose is to bootstrap development for new protocols and decrease boilerplate code.

Features

  • Simple non-blocking API
  • Not a protocol - sends only user's data without message wrapping on the wire
  • Not a framework - use it anyhow
  • Integrates generics in a clean way
  • Almost zero allocations API
  • Hides away stream management(re-creation, duplicates, lifecycle)

Background

The libp2p provides all necessary primitives to build custom fully decentralized p2p protocols. Also, it is solely stream-based for reasons, but in practice, the vast majority of libp2p based protocols are message-based, with messages sent over reliable and multiplexed streams.

Mainly, there are two typical patterns for message sending over streams.

Request/Response

The most popular pattern in libp2p protocols is sending requests over a fresh stream and waiting for a response with a subsequent closing. Using libp2p's bare Stream API is trivial for such a case, which also explains why it is the most popular pattern.

'Fire and Forget'

Another less common pattern in libp2p protocols is sending messages without expecting a response. Once instantiated, a protocol establishes a unique and persistent stream with a remote endpoint and only sends messages over it. This pattern optimizes protocols by removing unnecessary stream negotiations, which are primarily expensive for round trips.

Motivations

  • Provide reusable utility for common use-cases in libp2p protocol development.

    • Even for simple Request/Response pattern, there is some level of boilerplate that can be avoided (Examples: Bitswap, kadDHT)

      Currently, the Messenger does not provide a Request/Response semantics, and the main focus is 'fire and forget'.

    • 'Fire and Forget' is more complex. It can be implemented in multiple ways, has undesirable edge cases, and requires a more profound knowledge of the libp2p stack. Although the pattern is an interesting engineering challenge to solve, in business and rapidly changing environments, it is easier to reuse existing instruments, like Messenger.
  • Lower entrance threshold for new developers exploring decentralization and p2p networking.

  • Bootstrap migration of Tendermint over libp2p.

    Tendermint is the first and most popular BFT consensus implementation, and it is decentralized and requires p2p networking. The project's team, through time, developed an in-house solution for it. However, they are now committed to migration over libp2p.

    Tendermint is a towering stack of multiple sub-protocols(or their terms - reactors) which rely on patterns explained above. Therefore, a lesser code boilerplate and simple API would be convenient for such migration.

    Technically, Tendermint p2p stack only supports 'fire and forget' pattern, but a few sub-protocols can benefit from migration to Request/Response pattern.

Documentation

See these docs.

License

Apache-2.0.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Message added in v0.2.1

type Message interface {
	serde.Message
	// From points to peer the Message was received from.
	From() peer.ID
	// To points to Messenger the peer to send the Message to.
	To() peer.ID
}

Message is a contract that any user defined message has to satisfy to be sent via Messenger.

type MessageBase added in v0.2.1

type MessageBase struct {
	FromPeer, ToPeer peer.ID
}

MessageBase is a helper to struct that users may embed into their custom Message implementations. It's sole purpose is to minimize boilerplate code.

func (*MessageBase) From added in v0.2.1

func (mb *MessageBase) From() peer.ID

func (*MessageBase) To added in v0.2.1

func (mb *MessageBase) To() peer.ID

type Messenger

type Messenger[M Message] struct {
	// contains filtered or unexported fields
}

Messenger provides a simple API to send messages to multiple peers.

func New

func New[M Message](host host.Host, new NewMessageFn[M], opts ...Option) (*Messenger[M], error)

New instantiates a Messenger. WithProtocols option is mandatory for at least one protocol. WithMessageType overrides default serde.PlainMessage.

func (*Messenger[M]) Broadcast

func (m *Messenger[M]) Broadcast(ctx context.Context, out M) (peer.IDSlice, error)

Broadcast optimistically sends the given message 'out' to each connected peer speaking *the same* protocol. It returns a slice of peers to whom the message was sent and errors in case the given ctx was closed or in case when Messenger is closed. WARNING: It should be used deliberately. Avoid use cases requiring message propagation to a whole protocol network, not to flood the network with message duplicates. For such cases use libp2p.PubSub instead.

func (*Messenger[M]) Close

func (m *Messenger[M]) Close() error

Close stops the Messenger and unregisters further protocol handling on the Host.

func (*Messenger[M]) Host

func (m *Messenger[M]) Host() host.Host

Host is a getter for the Host.

func (*Messenger[M]) Peers added in v0.2.0

func (m *Messenger[M]) Peers() peer.IDSlice

Peers returns a list of connected/immediate peers speaking the protocol registered on the Messenger.

func (*Messenger[M]) Receive

func (m *Messenger[M]) Receive(ctx context.Context) (msg M, err error)

Receive awaits for incoming messages from peers. It receives messages sent through both Send and Broadcast. It errors only if the given context 'ctx' is closed or when Messenger is closed.

func (*Messenger[M]) Send

func (m *Messenger[M]) Send(ctx context.Context, out M) error

Send optimistically sends the given message 'out' to the peer 'to'. It errors in case the given ctx was closed or in case when Messenger is closed. All messages are sent in a per peer queue, so the ordering of sent messages is guaranteed. In case the Messenger is given with a RoutedHost, It tries to connect to the peer, if not connected.

type NewMessageFn added in v0.2.1

type NewMessageFn[M Message] func(from, to peer.ID) M

NewMessageFn is a type-parameterized constructor func for Message. It is required by Messenger, s.t. it can instantiate user-defined messages coming from the network.

type Option

type Option func(*options)

Option defines an functional configurability for Messenger.

func WithProtocols

func WithProtocols(pids ...protocol.ID) Option

WithProtocols sets custom protocols for messenger to speak with At least one protocol is required.

Directories

Path Synopsis
This library provides utilities for length-prefixed de/serialization for messages with user-specific serialization format.
This library provides utilities for length-prefixed de/serialization for messages with user-specific serialization format.

Jump to

Keyboard shortcuts

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