pastry

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: May 5, 2024 License: AGPL-3.0 Imports: 13 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// JoinProtocolNew indicates that we haven't even tried to start joining the
	// overlay network yet.
	JoinProtocolNew = JoinProtocolPhase(iota)

	// JoinProtocolBootstrapping indicates that e are joining the overlay
	// network.  We've sent out our initial JoinNetwork message, and we're
	// waiting for existing nodes to send us copies of their routing
	// information.
	JoinProtocolBootstrapping

	// JoinProtocolClaiming indicates that we have received routing information
	// from most of the nodes in between the bootstrap node and the previous
	// owner of our ID.  In particular, we have received a leaf set from the
	// previous owner, and we've sent a Claim message to the previous owner
	// letting them know that we exist.
	JoinProtocolClaiming

	// JoinPrortocolJoined indicates that we have received an acknowledgement
	// from the previous owner of our ID that we exist, and that they've
	// relinquished control of our portion of the ID space to us.  We can now
	// start broadcasting our existence to all of the other nodes that we
	// learned about during the bootstrapping phase.
	JoinProtocolJoined
)
View Source
const (
	// InterceptError indicates that there was an error in an Intercept method.
	// You must not return this value with a nil error.
	InterceptError = InterceptResult(iota)

	// Intercepted indicates that an intercept handler fully handled the routed
	// message, short-circuiting the default routing protocol.
	Intercepted

	// Forward indicates that an intercept handler chose not to handle a routed
	// message, allowing the Pastry routing layer to forward the routed message
	// using the normal routing protocol.
	//
	// Note that if you made any changes to the local routing state in your
	// Intercept method, those changes will *not* be taken into account when
	// determining the next hop for this routed message!
	Forward
)
View Source
const IdentifierByteLength = 16

IdentifierByteLength is number of bytes in a Pastry identifier.

View Source
const IdentifierDigitBitLength = 4

IdentifierDigitBitLength is the number of bits in a Pastry identifier digit.

View Source
const IdentifierDigitLength = IdentifierByteLength * 8 / IdentifierDigitBitLength

IdentifierDigitLength is the number of hexadecimal (4-bit) digits in a Pastry identifier.

View Source
const LeafSetSize = 16

LeafSetSize is the number of elements in each _half_ of a leaf set

View Source
const MaxStashedStringLength = 4096
View Source
const RoutingTableColumnCount = 1 << IdentifierDigitBitLength
View Source
const RoutingTableRowCount = IdentifierDigitLength
View Source
const UnknownProximity = math.MaxUint64

UnknownProximity indicates that we do not yet know how far away another Pastry node is.

Variables

View Source
var AnnounceID = CalculateMessageID("JoinProtocol:Announce")
View Source
var ClaimID = CalculateMessageID("JoinProtocol:Claim")
View Source
var FindJoiningNodeID = CalculateMessageID("JoinProtocol:FindJoiningNode")
View Source
var JoinNetworkID = CalculateMessageID("JoinProtocol:JoinNetwork")
View Source
var PingID = CalculateMessageID("Ping")
View Source
var PongID = CalculateMessageID("Pong")
View Source
var RelinquishID = CalculateMessageID("JoinProtocol:Relinquish")
View Source
var RestartID = CalculateMessageID("JoinProtocol:Restart")
View Source
var RouteMessageID = CalculateMessageID("RouteMessage")
View Source
var SendLeafSetID = CalculateMessageID("JoinProtocol:SendLeafSet")
View Source
var SendRoutingTableID = CalculateMessageID("JoinProtocol:SendRoutingTable")
View Source
var StashStringID = CalculateMessageID("StashString")

Functions

func GetOwner

func GetOwner(ids []Identifier, dest Identifier) int

GetOwner returns the index of which node owns a particular destination identifier. This is used in test cases to verify our routing logic.

func NewNoopTransport

func NewNoopTransport(logger *slog.Logger) *noopTransport

NewNoopTransport creates a Transport implementation that doesn't do anything.

func SortIdentifiersByDistance

func SortIdentifiersByDistance(ids []Identifier, target Identifier)

SortIdentifiersByDistance sorts ids by their distance to a target identifier, with the closest ID appearing first. (This means that if ids is the list of nodes in a network, ids[0] will be the node that owns the target identifier.)

func WriteIdentifier

func WriteIdentifier(payload *bytes.Buffer, value Identifier)

WriteIdentifier writes an identifier into a message payload buffer.

func WriteMessageID

func WriteMessageID(payload *bytes.Buffer, value MessageID)

WriteMessageID writes a message ID into a message payload buffer.

func WriteString

func WriteString(payload *bytes.Buffer, value string, maxLength int) error

WriteString writes a string into a message payload buffer. The string is encoded as an unsigned varint, followed immediately by its content. You must provide the maximum expected length of the string; if the string is longer than this, we return an error.

func WriteUint16

func WriteUint16(payload *bytes.Buffer, value uint16)

WriteUint16 writes a big-endian uint16 into a message payload buffer.

func WriteUint32

func WriteUint32(payload *bytes.Buffer, value uint32)

WriteUint32 writes a big-endian uint32 into a message payload buffer.

func WriteUint64

func WriteUint64(payload *bytes.Buffer, value uint64)

WriteUint64 writes a big-endian uint64 into a message payload buffer.

func WriteUint8

func WriteUint8(payload *bytes.Buffer, value uint8)

WriteUint8 writes a uint8 into a message payload buffer.

func WriteUvarint

func WriteUvarint(payload *bytes.Buffer, value uint64)

WriteUvarint writes an unsigned varint into a message payload buffer.

Types

type Announce

type Announce struct {
	JoiningNode Node
	Entries     []Node
}

Announce is sent by the joining node to every node that it learned about during the bootstrap process. This propagates information about the new node to the rest of the network.

func (*Announce) Decode

func (m *Announce) Decode(ml *MessageLibrary, p *MessagePayload) error

func (*Announce) Encode

func (m *Announce) Encode(ml *MessageLibrary, payload *bytes.Buffer) error

func (*Announce) MessageID

func (m *Announce) MessageID() MessageID

type Claim

type Claim struct {
	JoiningNode Node
}

Claim is sent by the joining node to its immediate left neighbor once it has received a useful amount of routing state. This indicates to the neighbor that the new joining node is ready to take control of its portion of the ID space.

func (*Claim) Decode

func (m *Claim) Decode(ml *MessageLibrary, p *MessagePayload) error

func (*Claim) Encode

func (m *Claim) Encode(ml *MessageLibrary, payload *bytes.Buffer) error

func (*Claim) MessageID

func (m *Claim) MessageID() MessageID

type Deliver

type Deliver interface {
	MessageType

	// Deliver is called when the local node is the owner of a routed message's
	// target identifier. You can assume that the [Message] that is passed in to
	// your handler is of the correct type. p.Original will contain the
	// serialized content of the routed message, which allows you to forward
	// messages without having to serialize a new copy.
	Deliver(
		ctx context.Context,
		source Identifier,
		target Identifier,
		msg Message,
		p *MessagePayload,
	) error
}

Deliver is implemented by Pastry modules that know how to process particular types of routed messages, where the local node is the owner of the target identifier.

type FindJoiningNode

type FindJoiningNode struct {
	JoiningNode Node
}

FindJoiningNode is routed by the bootstrap node towards the new node that it receives a JoinNetwork message from. All nodes along the path intercept this message and send part of their routing state to the new node. The node that's closest to the new node will also send its leaf set, since it should presumably overlap a lot with the new node's desired leaf set.

func (*FindJoiningNode) Decode

func (*FindJoiningNode) Encode

func (m *FindJoiningNode) Encode(ml *MessageLibrary, payload *bytes.Buffer) error

func (*FindJoiningNode) MessageID

func (m *FindJoiningNode) MessageID() MessageID

type Identifier

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

Identifier represents a 128-bit Pastry identifier.

func NewIdentifier

func NewIdentifier(bytes [IdentifierByteLength]byte) Identifier

NewIdentifier creates a new identifier from its big-endian binary encoding.

func NewIdentifierFromHexString

func NewIdentifierFromHexString(s string) Identifier

NewIdentifierFromHexString parses an identifier from its hex string representation. This is only intended for use in test cases; it will panic if the string is malformed.

func (Identifier) Bytes

func (id Identifier) Bytes() [IdentifierByteLength]byte

func (Identifier) Dual

func (id Identifier) Dual() Identifier

Dual returns the dual of an identifier (i.e. the identifier precisely opposite on the ring).

func (Identifier) Format

func (id Identifier) Format(state fmt.State, verb rune)

func (Identifier) GetDigit

func (id Identifier) GetDigit(index int) byte

GetDigit returns the hexadecimal (4-bit) digit in an identifier with a particular index. Indexes are numbered 0-31, inclusive. The result is undefined if you provide an invalid index number.

func (Identifier) GetMsdd

func (id1 Identifier) GetMsdd(id2 Identifier) int

GetMsdd returns the most-significant different digit between two identifiers. Returns IdentifierDigitLength if the identifiers are identical.

func (Identifier) IsBetween

func (id Identifier) IsBetween(a, b Identifier) bool

IsBetween returns whether this identifier is between [a, b).

func (Identifier) IsClockwiseOf

func (id1 Identifier) IsClockwiseOf(id2 Identifier) bool

IsClockwiseOf returns if one identifier is clockwise of another (id1 >= id2). An identifier is clockwise of itself.

func (Identifier) IsCloserTo

func (remoteID Identifier) IsCloserTo(localID Identifier, dest Identifier) bool

IsCloserTo returns whether a remote node's identifiers is closer to a destination than the local node's identifier.

func (Identifier) IsFallbackFor

func (remoteID Identifier) IsFallbackFor(localID Identifier, dest Identifier) bool

IsFallbackFor returns whether a remote node's identifier is a valid fallback next hop for a particular local node and destination. The remote identifier must have at least as many digits in common with the destination as the local identifier, and must also be numerically closer to the destination.

func (*Identifier) SetDigit

func (id *Identifier) SetDigit(index int, value byte)

SetDigit sets a particular the hexadecimal (4-bit) digit in an identifier. This is primarily intended to be used in test cases.

func (Identifier) String

func (id Identifier) String() string

type Intercept

type Intercept interface {
	MessageType

	// Intercept is called when the local node is not the owner of the routed
	// message's target identifier. You can assume that the [Message] that is
	// passed in to your handler is of the correct type. p.Original will contain
	// the serialized content of the routed message, which allows you to forward
	// messages without having to serialize a new copy.
	Intercept(
		ctx context.Context,
		source Identifier,
		target Identifier,
		msg Message,
		p *MessagePayload,
	) (InterceptResult, error)
}

Intercept is implemented by Pastry modules that need to override the default routing behavior for routed messages where the local node is not the owner of the target identifier. Intercept handlers are optional; if one is not provided for a message type, the router will use the default intercept logic (which is to forward the message on to another node that is closer to the message's destination).

type InterceptResult

type InterceptResult int

type JoinNetwork

type JoinNetwork struct {
	JoiningNode Node
}

JoinNetwork is sent by a new node that wants to join the overlay network. The new node sends this message to a "bootstrap node" directly (i.e., not via the routing table, since it doesn't have one yet). (You must configure the new node with the connection details for the bootstrap node out-of-band.)

In response to this message, the bootstrap node will cause several existing nodes to send routing table information to the new node.

func (*JoinNetwork) Decode

func (m *JoinNetwork) Decode(ml *MessageLibrary, p *MessagePayload) error

func (*JoinNetwork) Encode

func (m *JoinNetwork) Encode(ml *MessageLibrary, payload *bytes.Buffer) error

func (*JoinNetwork) MessageID

func (m *JoinNetwork) MessageID() MessageID

type JoinProtocol

type JoinProtocol struct {
	Phase JoinProtocolPhase
	// contains filtered or unexported fields
}

JoinProtocol is a Pastry module that implements the protocol by which new nodes join the network. It is responsible both for helping the local node join the network in the first place, and also for helping future nodes join the network.

func NewJoinProtocol

func NewJoinProtocol(
	transport Transport,
	transceiver *Transceiver,
	router *Router,
) *JoinProtocol

func (*JoinProtocol) Bootstrap

func (jp *JoinProtocol) Bootstrap(ctx context.Context, bootstrapNode Node) error

func (*JoinProtocol) StartNetwork

func (jp *JoinProtocol) StartNetwork(ctx context.Context) error

type JoinProtocolPhase

type JoinProtocolPhase int

func (JoinProtocolPhase) String

func (p JoinProtocolPhase) String() string

type LeafSet

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

LeafSet holds the leaf set for a Pastry node, which is the collection of nodes that are its closest neighbors in the identifier ring.

func NewLeafSet

func NewLeafSet(logger *slog.Logger, local Node) *LeafSet

func (*LeafSet) Add

func (ls *LeafSet) Add(entry Node)

Add adds a new entry to this leaf set. If all of the existing members of the leaf set are closer to the local node, the new entry is not added.

func (*LeafSet) Covers

func (ls *LeafSet) Covers(id Identifier) bool

Covers returns whether this leaf set can identify which node owns the given identifier.

func (*LeafSet) FallbackNextHop

func (ls *LeafSet) FallbackNextHop(dest Identifier) Node

FallbackNextHop determines the fallback forwarding node for messages destined for a particular identifier.

func (*LeafSet) ForEachEntry

func (ls *LeafSet) ForEachEntry(callback func(entry Node))

ForEachEntry invokes a callback for each remote node that is stored in this leaf set.

func (*LeafSet) NextHop

func (ls *LeafSet) NextHop(dest Identifier) Node

type Message

type Message interface {
	MessageID() MessageID

	// Decode deserializes a message payload.
	//
	// Implementors of this method should _not_ deserialize the type's
	// MessageID; that will have already been deserialized by the caller.
	Decode(ml *MessageLibrary, p *MessagePayload) error

	// Encode serializes the contents of this message into a payload buffer.
	//
	//
	// Implementors of this method should _not_ serialize the type's MessageID;
	// that will have already been serialized by the caller.
	Encode(ml *MessageLibrary, payload *bytes.Buffer) error
}

Message is implemented by message types that can deserialized and sent between nodes on the overlay network.

type MessageID

type MessageID uint32

MessageID is a unique identifier for a message type that can be sent between Pastry nodes. A MessageID is typically the first 4 bytes of the SHA-512 hash of the name of the message type. Use CalculateMessageID to produce one.

func CalculateMessageID

func CalculateMessageID(name string) MessageID

CalculateMessageID calculates the MessageID for a particular message type given its name.

func (MessageID) String

func (id MessageID) String() string

type MessageLibrary

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

MessageLibrary knows about all of the message types that the local node knows how to decode and process.

func NewMessageLibrary

func NewMessageLibrary(transport Transport) *MessageLibrary

func (*MessageLibrary) DecodeAnyMessage

func (ml *MessageLibrary) DecodeAnyMessage(p *MessagePayload) (Message, error)

DecodeAnyMessage verifies that a message payload contains a message of any known type, and then deserializes it.

func (*MessageLibrary) DecodeMessage

func (ml *MessageLibrary) DecodeMessage(p *MessagePayload, msg Message) error

DecodeMessage verifies that a message payload contains a message of the requested type, and then deserializes it.

func (*MessageLibrary) EncodeMessage

func (ml *MessageLibrary) EncodeMessage(payload *bytes.Buffer, msg Message) error

EncodeMessage serializes a message into a payload, along with its message ID.

func (*MessageLibrary) GetMessageType

func (ml *MessageLibrary) GetMessageType(id MessageID) (MessageType, error)

GetMessageType returns the MessageType for a particular message ID, or an error if one doesn't exist.

func (*MessageLibrary) ReadNode

func (ml *MessageLibrary) ReadNode(p *MessagePayload) (Node, error)

ReadNode reads from a message payload the transport-specific information needed to identify a Pastry node, and returns a Node reference to it.

func (*MessageLibrary) RegisterMessageType

func (ml *MessageLibrary) RegisterMessageType(mt MessageType) MessageID

RegisterMessageType registers a new message type. Panics if there is already a message type with the same message ID, and the two do not return an instance of the same Go type.

type MessagePayload

type MessagePayload struct {
	Original  []byte
	Remaining []byte
}

MessagePayload wraps a binary message payload received from another Pastry node, and provides methods for deserializing its content.

func NewMessagePayload

func NewMessagePayload(payload []byte) MessagePayload

NewMessagePayload creates a new MessagePayload wrapping a message payload.

func (*MessagePayload) Consume

func (p *MessagePayload) Consume(dest []byte) error

Consume consumes bytes from a message payload. If there is not enough content remaining in the payload to fill the output slice, we return an error.

func (*MessagePayload) ConsumeByte

func (p *MessagePayload) ConsumeByte() (byte, error)

ConsumeByte ensures that there is at least one byte remaining in the message payload, and consumes and returns it.

func (*MessagePayload) ReadIdentifier

func (p *MessagePayload) ReadIdentifier() (Identifier, error)

ReadIdentifier reads an identifier from the message payload, consuming it.

func (*MessagePayload) ReadMessageID

func (p *MessagePayload) ReadMessageID() (MessageID, error)

ReadMessageID reads a message ID from the message payload, consuming it.

func (*MessagePayload) ReadString

func (p *MessagePayload) ReadString(maxLength int) (string, error)

ReadString reads a string from the message payload, consuming it. The string is encoded as an unsigned varint, followed immediately by its content. You must provide the maximum expected length of the string; if the length prefix indicates a string longer than this, we return an error.

func (*MessagePayload) ReadUint16

func (p *MessagePayload) ReadUint16() (uint16, error)

ReadUint16 reads a big-endian uint16 from the message payload, consuming it.

func (*MessagePayload) ReadUint32

func (p *MessagePayload) ReadUint32() (uint32, error)

ReadUint32 reads a big-endian uint32 from the message payload, consuming it.

func (*MessagePayload) ReadUint64

func (p *MessagePayload) ReadUint64() (uint64, error)

ReadUint64 reads a big-endian uint64 from the message payload, consuming it.

func (*MessagePayload) ReadUint8

func (p *MessagePayload) ReadUint8() (uint8, error)

ReadUint8 reads a uint8 from the message payload, consuming it.

func (*MessagePayload) ReadUvarint

func (p *MessagePayload) ReadUvarint() (uint64, error)

ReadUvarint reads an unsigned varint from the message payload, consuming it.

type MessageType

type MessageType interface {
	// EmptyMessage returns an empty message of the type described by this
	// instance.
	EmptyMessage() Message
}

MessageType describes one of the message types that the local node knows how to decode and process.

type Node

type Node interface {
	NodeID() Identifier
	IsLocal() bool

	// CurrentProximity returns the current estimate for how close this node is
	// to the local node. This method should return quickly; in particular, it
	// should not perform I/O to determine the proximity.  The proximity should
	// be calculated in the background, or as part of the ongoing communication
	// with the node, with the most recent value kept around in local state.
	// This method should be a simple getter method on that local state.  Return
	// UnknownProximity if you have not yet been able to determine how close the
	// remote node is.
	CurrentProximity() Proximity

	// Send sends a message to another Pastry node via the underlay network.
	Send(ctx context.Context, payload []byte) error

	// Write writes into a message payload the transport-specific information
	// needed to identify this node.
	Write(payload *bytes.Buffer) error
}

type Ping

type Ping struct {
	From  Node
	Nonce uint64
}

func (*Ping) Decode

func (m *Ping) Decode(ml *MessageLibrary, p *MessagePayload) error

func (*Ping) Encode

func (m *Ping) Encode(ml *MessageLibrary, payload *bytes.Buffer) error

func (*Ping) MessageID

func (m *Ping) MessageID() MessageID

type PingCallback

type PingCallback func(nonce uint64, owner Node)

type PingPong

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

PingPong is a simple Pastry module that receives Ping messages, and sends back a Pong message in response. It is useful to verify low-level connectivity in the Pastry network.

func NewPingPong

func NewPingPong(
	transport Transport,
	transceiver *Transceiver,
	router *Router,
) *PingPong

func (*PingPong) RoutePing

func (pp *PingPong) RoutePing(ctx context.Context, target Identifier, callback PingCallback) error

func (*PingPong) SendPing

func (pp *PingPong) SendPing(ctx context.Context, dest Node, callback PingCallback) error

type Pong

type Pong struct {
	From  Node
	Nonce uint64
}

func (*Pong) Decode

func (m *Pong) Decode(ml *MessageLibrary, p *MessagePayload) error

func (*Pong) Encode

func (m *Pong) Encode(ml *MessageLibrary, payload *bytes.Buffer) error

func (*Pong) MessageID

func (m *Pong) MessageID() MessageID

type Proximity

type Proximity uint64

Proximity represents how far away another Pastry node is on the underlay network.

type Receive

type Receive interface {
	MessageType

	// Receive is called for every message of a particular type that is received
	// by the local node. You can assume that the [Message] that is passed in to
	// your handler is of the correct type. p.Original will contain the
	// serialized content of the routed message, which allows you to forward
	// messages without having to serialize a new copy.
	Receive(ctx context.Context, msg Message, p *MessagePayload) error
}

Receive is implemented by Pastry modules that know how to process particular types of messages that can be received from other nodes on the network.

type Relinquish

type Relinquish struct {
	From Node
}

Relinquish is sent by the joining node's immediate left neighbor to let the joining node know that it has acknowledged that new node's claim to its portion of the ID space. This neighbor was the previous owner of the ID space, and before sending this message, it will update its own routing state to include the new node. This ensures that, even if the rest of the network does not yet know about the new node, messages will get routed to the new node correctly, using the previous owner as a bottleneck until that knowledge propagates.

func (*Relinquish) Decode

func (m *Relinquish) Decode(ml *MessageLibrary, p *MessagePayload) error

func (*Relinquish) Encode

func (m *Relinquish) Encode(ml *MessageLibrary, payload *bytes.Buffer) error

func (*Relinquish) MessageID

func (m *Relinquish) MessageID() MessageID

type Restart

type Restart struct {
	From Node
}

Restart is sent to the joining node from the node that it _thought_ was its immediate left neighbor if that node is no longer its immediate left neighbor. This indicates that some _other_ nearby node joined at roughly the same time. Instead of trying to have both joining nodes come to an agreement about where they belong in the overlay, one of them will be told to restart the bootstrap process completely.

func (*Restart) Decode

func (m *Restart) Decode(ml *MessageLibrary, p *MessagePayload) error

func (*Restart) Encode

func (m *Restart) Encode(ml *MessageLibrary, payload *bytes.Buffer) error

func (*Restart) MessageID

func (m *Restart) MessageID() MessageID

type RouteMessage

type RouteMessage struct {
	Source Identifier
	Target Identifier
	Msg    Message
}

func (*RouteMessage) Decode

func (m *RouteMessage) Decode(ml *MessageLibrary, p *MessagePayload) error

func (*RouteMessage) Encode

func (m *RouteMessage) Encode(ml *MessageLibrary, payload *bytes.Buffer) error

func (*RouteMessage) MessageID

func (m *RouteMessage) MessageID() MessageID

type Router

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

Router is a Pastry module that implements the Pastry routing protocol, allowing you to send routed messages “towards” a particular target identifier. The routers on each of the Pastry nodes collectively decide which nodes “own” regions of the identifier space. The routing protocol ensures that a routed message reaches the node that owns the target identifier.

func NewRouter

func NewRouter(transport Transport, ml *MessageLibrary, transceiver *Transceiver) *Router

func (*Router) Add

func (r *Router) Add(node Node)

Add adds a new remote node to a router's routing state. You will typically not need to call this directly; it will be called automatically as part of the routing table maintainance background process.

func (*Router) ForEachEntry

func (r *Router) ForEachEntry(callback func(entry Node))

ForEachEntry invokes a callback for each remote node that is stored in this router.

func (*Router) LeafSet

func (r *Router) LeafSet() *LeafSet

LeafSet returns the router's leaf set.

func (*Router) NextHop

func (r *Router) NextHop(dest Identifier) (Node, string)

NextHop determines the forwarding node for messages destined for a particular identifier.

func (*Router) Owns

func (r *Router) Owns(dest Identifier) bool

Owns determines whether the local node is the owner of a particular identifier.

func (*Router) RegisterDeliver

func (r *Router) RegisterDeliver(deliver Deliver)

RegisterDeliver registers a deliver handler. There must not already be a deliver handler for the same message ID.

func (*Router) RegisterIntercept

func (r *Router) RegisterIntercept(intercept Intercept)

RegisterIntercept registers an interceptor handler. There must not already be a intercept handler for the same message ID.

func (*Router) Route

func (r *Router) Route(ctx context.Context, target Identifier, msg Message) error

Route serializes a routed message and sends it towards a target identifier. The local identifier is used as the source of the routed message.

func (*Router) RouteWithSource

func (r *Router) RouteWithSource(
	ctx context.Context,
	source Identifier,
	target Identifier,
	msg Message,
) error

RouteWithSource serializes a routed message and sends it towards a target identifier.

func (*Router) RoutingTable

func (r *Router) RoutingTable() *RoutingTable

RoutingTable returns the router's routing table.

type RoutingTable

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

RoutingTable holds the routing table for a Pastry node.

func NewRoutingTable

func NewRoutingTable(logger *slog.Logger, local Node) *RoutingTable

func (*RoutingTable) Add

func (rt *RoutingTable) Add(node Node)

Add adds a node to this routing table.

func (*RoutingTable) FallbackNextHop

func (rt *RoutingTable) FallbackNextHop(dest Identifier) Node

FallbackNextHop determines the fallback forwarding node for messages destined for a particular identifier.

func (*RoutingTable) ForEachEntry

func (rt *RoutingTable) ForEachEntry(callback func(entry Node))

ForEachEntry invokes a callback for each remote node that is stored in this routing table.

func (*RoutingTable) ForEachEntryInRow

func (rt *RoutingTable) ForEachEntryInRow(r int, callback func(entry Node))

ForEachEntryInRows invokes a callback for each remote node that is stored in a specific row of this routing table.

func (*RoutingTable) ForEachEntryInRows

func (rt *RoutingTable) ForEachEntryInRows(rowCount int, callback func(entry Node))

ForEachEntryInRows invokes a callback for each remote node that is stored in the first few rows of this routing table.

func (*RoutingTable) NextHop

func (rt *RoutingTable) NextHop(dest Identifier) Node

NextHop determines the forwarding node for messages destined for a particular identifier.

type SendLeafSet

type SendLeafSet struct {
	From    Node
	Entries []Node
}

SendLeafSet allows nodes to send their leaf sets to each other. Nodes will typically only send this if they know that they're "close" to the destination node, since that implies that their leaf sets are likely to overlap.

func (*SendLeafSet) Decode

func (m *SendLeafSet) Decode(ml *MessageLibrary, p *MessagePayload) error

func (*SendLeafSet) Encode

func (m *SendLeafSet) Encode(ml *MessageLibrary, payload *bytes.Buffer) error

func (*SendLeafSet) MessageID

func (m *SendLeafSet) MessageID() MessageID

type SendRoutingTable

type SendRoutingTable struct {
	From    Node
	Entries []Node
}

SendRoutingTable allows nodes use to send parts of their routing tables to each other.

func (*SendRoutingTable) Decode

func (*SendRoutingTable) Encode

func (m *SendRoutingTable) Encode(ml *MessageLibrary, payload *bytes.Buffer) error

func (*SendRoutingTable) MessageID

func (m *SendRoutingTable) MessageID() MessageID

type StashString

type StashString struct {
	Value string
}

func (*StashString) Decode

func (m *StashString) Decode(ml *MessageLibrary, p *MessagePayload) error

func (*StashString) Encode

func (m *StashString) Encode(ml *MessageLibrary, payload *bytes.Buffer) error

func (*StashString) MessageID

func (m *StashString) MessageID() MessageID

type StashStrings

type StashStrings struct {
	Received []string
	// contains filtered or unexported fields
}

StashStrings is a simple Pastry module that receives StashString messages, and saves any that are received. It is useful in test cases to verify message delivery works as expected.

func NewStashStrings

func NewStashStrings(transport Transport, transceiver *Transceiver, router *Router) *StashStrings

func (*StashStrings) RouteStashString

func (ss *StashStrings) RouteStashString(ctx context.Context, target Identifier, value string) error

func (*StashStrings) SendStashString

func (ss *StashStrings) SendStashString(ctx context.Context, dest Node, value string) error

type Transceiver

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

Transceiver is a Pastry module that is responsible for sending messages to and receiving messages from other nodes on the network. (Transceiver defines what to do in response to messages arriving and how to encode a message into a binary payload; a Transport implementation handles the low-level details of actually sending and receiving message content on a particular underlay network.)

Note that Transceiver is not responsible for _routing_ messages towards an arbitrary Pastry identifier; that is handled by a Router. Transceiver is only responsible for point-to-point communication between specific nodes on the network.

func NewTransceiver

func NewTransceiver(transport Transport, ml *MessageLibrary) *Transceiver

func (*Transceiver) Receive

func (t *Transceiver) Receive(ctx context.Context, p *MessagePayload) error

Receive processes a message received from some other node on the network.

func (*Transceiver) RegisterReceive

func (t *Transceiver) RegisterReceive(receive Receive)

RegisterReceive registers a receive handler. There must not already be a receive handler for the same message ID. You can assume that the Message that is passed in to your handler is of the correct type.

func (*Transceiver) Send

func (t *Transceiver) Send(ctx context.Context, dest Node, msg Message) error

Send serializes a message into a payload and sends that payload to a specific node on the overlay network.

type Transport

type Transport interface {
	// LocalNode returns the local node.
	LocalNode() Node

	// Logger returns an slog Logger that should be used for all log messages
	// involving the local node. You will typically use Logger.With to ensure
	// that all log messages include fields describing the local node.
	Logger() *slog.Logger

	// ReadNode reads from a message payload the transport-specific information
	// needed to identify a Pastry node, and returns a Node reference to it.
	ReadNode(p *MessagePayload) (Node, error)
}

Transport defines how a Pastry node belongs to and interacts with the underlay network (the lower-level network that Pastry nodes use to communicate with each other).

type UniqueNodes

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

UniqueNodes is a helper type for building up a list of unique nodes.

func (*UniqueNodes) Add

func (un *UniqueNodes) Add(entry Node)

func (*UniqueNodes) Len

func (un *UniqueNodes) Len() int

func (*UniqueNodes) Nodes

func (un *UniqueNodes) Nodes() []Node

func (*UniqueNodes) Reset

func (un *UniqueNodes) Reset()

Directories

Path Synopsis
Package connected provides a pastry transport implementation where all nodes live within the same process and can communicate with each other directly.
Package connected provides a pastry transport implementation where all nodes live within the same process and can communicate with each other directly.
Package isolated provides a pastry transport implementation that does not actually communicate with other nodes.
Package isolated provides a pastry transport implementation that does not actually communicate with other nodes.
Package pastrytest provides various helpers for testing Pastry networks.
Package pastrytest provides various helpers for testing Pastry networks.

Jump to

Keyboard shortcuts

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