proto

package
v0.0.0-...-0e38c20 Latest Latest
Warning

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

Go to latest
Published: Feb 20, 2024 License: MIT Imports: 9 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var CouldNotParsePacketErr = fmt.Errorf("could not parse data")

CouldNotParsePacketErr indicates that a parsing operation could not yield a valid result from the provided data buffer.

View Source
var NodeHashZero = NodeHash{}
View Source
var PacketDecoder = fsm.Def[Packet, packetDecoderState, packetDecoderContext]{
	Feed: func(f *fsm.FSM[Packet, packetDecoderState, packetDecoderContext], state packetDecoderState, ctx *packetDecoderContext, b byte) error {
		switch state {
		case packetDecoderStateHeader:
			head, err := ctx.headerDecoder.Feed(b)
			if err != nil {
				return err
			}

			if head != nil {
				decoder, ok := messageDecoderList[head.OpCode]
				if !ok {
					return NoDecoderError{op: head.OpCode}
				}

				f.Value.Header = *head

				if decoder == nil {
					t, ok := emptyMessageTypes[f.Value.Header.OpCode]
					if ok {
						f.Value.Message = reflect.New(t).Interface().(Message)
					}
					return fsm.Done
				}

				ctx.payloadDecoder = decoder.NewGeneric()
				f.Transition(packetDecoderStatePayload)
			}
		case packetDecoderStatePayload:
			msg, err := ctx.payloadDecoder.FeedAny(b)
			if err != nil {
				return err
			}
			if msg != nil {
				f.Value.Message = msg.(Message)
				return fsm.Done
			}
		}

		return nil
	},
}
View Source
var TCPPacketDecoder = fsm.Def[TCPPacket, tcpPacketDecoderState, struct{}]{
	InitialSize: 2,
	Feed: func(f *fsm.FSM[TCPPacket, tcpPacketDecoderState, struct{}], state tcpPacketDecoderState, ctx *struct{}, b byte) error {
		switch state {
		case tcpPacketDecoderStateMagic:
			if f.U16() != protocolMagic {
				f.Reset()
				return nil
			}
			f.Value.Magic = protocolMagic

			f.TransitionSatisfySize(tcpPacketDecoderStateVersion, 1)

		case tcpPacketDecoderStateVersion:
			if b != 1 {
				f.Reset()
				return nil
			}
			f.Value.Version = b

			f.TransitionSatisfySize(tcpPacketDecoderStateSize, 4)

		case tcpPacketDecoderStateSize:
			f.Value.Payload = make([]byte, f.U32())
			f.TransitionSatisfySize(tcpPacketDecoderStatePayload, len(f.Value.Payload))

		case tcpPacketDecoderStatePayload:
			f.CopyPayload(f.Value.Payload)
			return fsm.Done
		}

		return nil
	},
}.IntoExported()

TCPPacketDecoder is responsible for decoding a TCP stream into TCPPacket(s)

Functions

func EncPkt

func EncPkt(incarnation uint16, message Message) []byte

EncPkt encodes a given Message with a given incarnation identifier into a Packet, and returns its bytes.

Types

type AddressKind

type AddressKind uint8

AddressKind indicates which kind of address is contained within a message or substructure

const (
	AddressIPv4 AddressKind = 0
	AddressIPv6 AddressKind = 1
)

func (AddressKind) Size

func (a AddressKind) Size() int

Size returns the amount of bytes required to represent this AddressKind

func (AddressKind) String

func (i AddressKind) String() string

func (AddressKind) UnixProto

func (a AddressKind) UnixProto() int

UnixProto returns the Unix syscall value representing the current AddressKind

type Alive

type Alive struct {
	Subject     IP
	Incarnation uint16
}

Alive represents the value of an EventAlive event. It refutes a Suspect event, given that { Alive.Incarnation=j, Suspect.Incarnation=i }, j > i.

func (*Alive) Encode

func (a *Alive) Encode(into []byte)

func (*Alive) FromNode

func (a *Alive) FromNode(n *Node)

func (*Alive) GetIncarnation

func (a *Alive) GetIncarnation() uint16

func (*Alive) GetSubject

func (a *Alive) GetSubject() IP

func (*Alive) Invalidates

func (a *Alive) Invalidates(current *Event) bool

func (*Alive) Kind

func (a *Alive) Kind() EventKind

func (*Alive) RequiredSize

func (a *Alive) RequiredSize() int

func (*Alive) SourceAddressKind

func (a *Alive) SourceAddressKind() AddressKind

func (*Alive) SubjectAddressKind

func (a *Alive) SubjectAddressKind() AddressKind

type BootstrapAck

type BootstrapAck struct{}

BootstrapAck represents a response for a BootstrapResponse, and contains no fields. This message is emitted to the control socket of a node to indicate that the bootstrap process can now proceed through the TCP channel. This is required to prevent multiple bootstrap responders to try to connect to the same node requesting bootstrap.

func (BootstrapAck) Encode

func (BootstrapAck) Encode([]byte)

func (BootstrapAck) OpCode

func (BootstrapAck) OpCode() OpCode

func (BootstrapAck) RequiredSize

func (BootstrapAck) RequiredSize() int

type BootstrapRequest

type BootstrapRequest struct{}

BootstrapRequest represents a bootstrap message emitted in a multicast network. Other nodes listening to the same network may respond to this message by emitting a UDP Unicast BootstrapResponse.

func (BootstrapRequest) Encode

func (BootstrapRequest) Encode([]byte)

func (BootstrapRequest) OpCode

func (BootstrapRequest) OpCode() OpCode

func (BootstrapRequest) RequiredSize

func (BootstrapRequest) RequiredSize() int

type BootstrapResponse

type BootstrapResponse struct{}

BootstrapResponse represents a response for a BootstrapRequest, and contains no fields. The node's address can be obtained through the Packet structure wrapping this BootstrapResponse, and the responding node's incarnation number can be obtained from Header.Incarnation, also present in the upper Packet structure.

func (BootstrapResponse) Encode

func (BootstrapResponse) Encode([]byte)

func (BootstrapResponse) OpCode

func (BootstrapResponse) OpCode() OpCode

func (BootstrapResponse) RequiredSize

func (BootstrapResponse) RequiredSize() int

type Encoder

type Encoder interface {
	// RequiredSize returns the amount of bytes required to encode the current
	// structure.
	RequiredSize() int

	// Encode takes a slice of bytes and writes the current structure's
	// serialized representation into it. It assumes that len(into) is equal or
	// greater to the value returned by RequiredSize.
	Encode(into []byte)
}

Encoder represents any structure that can be encoded by Writer or any other decoding facility

type Event

type Event struct {
	Payload EventEncoder
}

Event represents a single event that occurred against a given IP.

func (Event) Encode

func (e Event) Encode(into []byte)

func (Event) EventKind

func (e Event) EventKind() EventKind

EventKind returns the associated EventKind from the current payload.

func (Event) RequiredSize

func (e Event) RequiredSize() int

func (Event) String

func (e Event) String() string

type EventEncoder

type EventEncoder interface {
	Encoder
	Kind() EventKind
	SourceAddressKind() AddressKind
	SubjectAddressKind() AddressKind
	GetIncarnation() uint16
	GetSubject() IP
	Invalidates(other *Event) bool
}

EventEncoder represents a structure capable of encoding an Event

type EventKind

type EventKind uint8
const (
	// EventJoin represents an event indicating that a new member has been added
	// to the cluster after a known member bootstraps it.
	EventJoin EventKind = 0b0000

	// EventHealthy indicates that a cluster member asserted a given node as
	// healthy, after it has been suspected as faulty.
	EventHealthy EventKind = 0b0001

	// EventSuspect indicates that a cluster member suspects that a given node
	// is suspected to be faulty.
	EventSuspect EventKind = 0b0010

	// EventFaulty indicates that a cluster member could not be reached for a
	// given period of time and is no longer considered a member of the current
	// cluster.
	EventFaulty EventKind = 0b0011

	// EventLeft is voluntarily emitted by nodes before they leave the cluster,
	// potentially avoiding a whole suspect->indirect ping->faulty check by
	// other cluster members.
	EventLeft EventKind = 0b0100

	// EventAlive is emitted by nodes that noticed their healthiness was being
	// suspected, in order to indicate that it is actually running and able to
	// be part of the cluster.
	EventAlive EventKind = 0b0101

	// EventWrap is emitted by nodes to indicate that their incarnation count
	// will wrap back to zero after exhausting other uint16 values.
	EventWrap EventKind = 0b0110
)

func (EventKind) String

func (i EventKind) String() string

type Faulty

type Faulty struct {
	Source      IP
	Subject     IP
	Incarnation uint16
}

Faulty represents the value of an EventFaulty, and indicates that Source assumed { Subject, inc=Incarnation } as faulty due to lack of response and failure to receive responses from indirect pings.

func (*Faulty) Encode

func (f *Faulty) Encode(into []byte)

func (*Faulty) FromNode

func (f *Faulty) FromNode(n *Node)

func (*Faulty) GetIncarnation

func (f *Faulty) GetIncarnation() uint16

func (*Faulty) GetSubject

func (f *Faulty) GetSubject() IP

func (*Faulty) Invalidates

func (f *Faulty) Invalidates(current *Event) bool

func (*Faulty) Kind

func (f *Faulty) Kind() EventKind

func (*Faulty) RequiredSize

func (f *Faulty) RequiredSize() int

func (*Faulty) SetSource

func (f *Faulty) SetSource(addr *IP)

func (*Faulty) SourceAddressKind

func (f *Faulty) SourceAddressKind() AddressKind

func (*Faulty) SubjectAddressKind

func (f *Faulty) SubjectAddressKind() AddressKind
type Header struct {
	Magic       uint16
	Version     uint8
	OpCode      OpCode
	Incarnation uint16
}

Header is a structure present in every exchanged message. It contains the protocol magic bytes, the version to which the message belongs to, the message type, and the incarnation identifier of the member that emitted this it.

func (Header) Encode

func (h Header) Encode(into []byte)

func (Header) RequiredSize

func (h Header) RequiredSize() int

type Healthy

type Healthy struct {
	Source      IP
	Subject     IP
	Incarnation uint16
}

Healthy represents the value of an EventHealthy and indicates that Source assumed { Subject, inc=Incarnation } as healthy, after a protocol period.

func (*Healthy) Encode

func (h *Healthy) Encode(into []byte)

func (*Healthy) FromNode

func (h *Healthy) FromNode(n *Node)

func (*Healthy) GetIncarnation

func (h *Healthy) GetIncarnation() uint16

func (*Healthy) GetSubject

func (h *Healthy) GetSubject() IP

func (*Healthy) Invalidates

func (h *Healthy) Invalidates(current *Event) bool

func (*Healthy) Kind

func (h *Healthy) Kind() EventKind

func (*Healthy) RequiredSize

func (h *Healthy) RequiredSize() int

func (*Healthy) SetSource

func (h *Healthy) SetSource(ip *IP)

func (*Healthy) SourceAddressKind

func (h *Healthy) SourceAddressKind() AddressKind

func (*Healthy) SubjectAddressKind

func (h *Healthy) SubjectAddressKind() AddressKind

type IP

type IP struct {
	AddressKind  AddressKind
	AddressBytes [16]byte
}

IP stores an AddressKind along with the bytes comprising it

func IPFromAddr

func IPFromAddr(addr netip.Addr) IP

IPFromAddr returns a new IP from a given netip.Addr structure.

func IPFromNetIP

func IPFromNetIP(ip net.IP) (out IP)

IPFromNetIP returns a new IP from a given net.IP structure.

func (IP) Bytes

func (i IP) Bytes() []byte

Bytes returns a slice of bytes representing this IP

func (IP) Equal

func (i IP) Equal(o *IP) bool

Equal returns whether the current IP is equal to the provided value

func (IP) IntoHash

func (i IP) IntoHash() NodeHash

func (IP) IntoManaged

func (i IP) IntoManaged() netip.Addr

IntoManaged returns the net.IP representation for the current IP

func (IP) Size

func (i IP) Size() int

Size returns the amount of bytes required to represent this IP

func (IP) String

func (i IP) String() string

String returns the string representation of the current IP

type IndirectPing

type IndirectPing struct {
	// Cookie is a random value generated by the requester to identify this ping
	// request. It must be relayed back as is to it.
	Cookie uint16

	// Period represents the protocol period in which the host was when sending
	// this request. It must be relayed back as is to it.
	Period uint16

	// Address represents the address to perform a ping against.
	Address IP
}

IndirectPing represents a request sent by a member suspecting that another member is faulty.

func (IndirectPing) Encode

func (i IndirectPing) Encode(into []byte)

func (IndirectPing) OpCode

func (i IndirectPing) OpCode() OpCode

func (IndirectPing) RequiredSize

func (i IndirectPing) RequiredSize() int

type IndirectPong

type IndirectPong struct {
	Cookie uint16
	Period uint16
}

IndirectPong represents a response for a IndirectPing

func (IndirectPong) Encode

func (i IndirectPong) Encode(into []byte)

func (IndirectPong) OpCode

func (i IndirectPong) OpCode() OpCode

func (IndirectPong) RequiredSize

func (i IndirectPong) RequiredSize() int

type Join

type Join struct {
	Source      IP
	Subject     IP
	Incarnation uint16
}

Join represents the value of an EventJoin, and indicates that a node Source has allowed{ Subject, inc = Incarnation } to join the current cluster.

func (*Join) Encode

func (j *Join) Encode(into []byte)

func (*Join) FromNode

func (j *Join) FromNode(n *Node)

func (*Join) GetIncarnation

func (j *Join) GetIncarnation() uint16

func (*Join) GetSubject

func (j *Join) GetSubject() IP

func (*Join) Invalidates

func (j *Join) Invalidates(current *Event) bool

func (*Join) Kind

func (j *Join) Kind() EventKind

func (*Join) RequiredSize

func (j *Join) RequiredSize() int

func (*Join) SetSource

func (j *Join) SetSource(addr *IP)

func (*Join) SourceAddressKind

func (j *Join) SourceAddressKind() AddressKind

func (*Join) SubjectAddressKind

func (j *Join) SubjectAddressKind() AddressKind

type Left

type Left struct {
	Subject     IP
	Incarnation uint16
}

Left represents the value of an EventLeft, and indicates that a given node Subject intends to leave the cluster immediately. This prevents other nodes from wasting resources trying to reach a node that left a cluster in a graceful manner.

func (*Left) Encode

func (l *Left) Encode(into []byte)

func (*Left) FromNode

func (l *Left) FromNode(n *Node)

func (*Left) GetIncarnation

func (l *Left) GetIncarnation() uint16

func (*Left) GetSubject

func (l *Left) GetSubject() IP

func (*Left) Invalidates

func (l *Left) Invalidates(current *Event) bool

func (*Left) Kind

func (l *Left) Kind() EventKind

func (*Left) RequiredSize

func (l *Left) RequiredSize() int

func (*Left) SourceAddressKind

func (l *Left) SourceAddressKind() AddressKind

func (*Left) SubjectAddressKind

func (l *Left) SubjectAddressKind() AddressKind

type Message

type Message interface {
	OpCode() OpCode
	Encoder
}

Message abstracts relevant methods of a message

type NoDecoderError

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

NoDecoderError indicates that this library does not have a decoder for a given received message.

func (NoDecoderError) Error

func (n NoDecoderError) Error() string

type NoEventDecoderError

type NoEventDecoderError struct {
	DecoderID uint8
}

NoEventDecoderError indicates that this library does not have a decoder for given received event.

func (NoEventDecoderError) Error

func (n NoEventDecoderError) Error() string

type Node

type Node struct {
	/// Suspect denotes whether a node, as perceived by the transmitting node,
	// is potentially in a StateFaulty condition.
	Suspect bool

	// Incarnation represents the last known incarnation ID of this node.
	Incarnation uint16

	// Address represents the address of this member.
	Address IP
}

Node represents a member of the cluster.

func (Node) Encode

func (n Node) Encode(into []byte)

func (Node) Equal

func (n Node) Equal(other Node) bool

Equal determines whether a given Node is equal another given Node.

func (Node) Hash

func (n Node) Hash() NodeHash

Hash returns a hashed representation of the current node's address in the form of a NodeHash

func (Node) RequiredSize

func (n Node) RequiredSize() int

func (Node) String

func (n Node) String() string

type NodeHash

type NodeHash struct{ netip.Addr }

NodeHash is a container type responsible for representing a Node unique identifier, which for our purposes, is the identity of the Node's IP address bytes.

type NodeInheritor

type NodeInheritor interface {
	FromNode(n *Node)
}

NodeInheritor represents a structure that can update its own values given a Node instance.

type OpCode

type OpCode uint8
const (
	// BTRP is a BootstrapRequest message
	BTRP OpCode = 0x01
	// BTRR is a BootstrapResponse message
	BTRR OpCode = 0x02
	// BTRA is a BootstrapAck message
	BTRA OpCode = 0x03
	// PING is a Ping message
	PING OpCode = 0x04
	// PONG is a Pong message
	PONG OpCode = 0x05
	// IING is an IndirectPing message
	IING OpCode = 0x06
	// IONG is an IndirectPong message
	IONG OpCode = 0x07
	// SYNC is a FullSync message
	SYNC OpCode = 0x08
)

func (OpCode) String

func (i OpCode) String() string

type Packet

type Packet struct {
	Source  net.IP
	Header  Header
	Message Message
}

Packet contains a Header and a Message object. Additionally, Packet may contain an extra Source, representing the IP from which the message came from.

func ParsePacket

func ParsePacket(data []byte) (*Packet, error)

ParsePacket attempts to parse a provided data byte slice into a Packet structure, including its payload. Returns an error in case the operation does not yield a valid Packet.

func Pkt

func Pkt(incarnation uint16, msg Message) *Packet

func (Packet) Encode

func (p Packet) Encode(into []byte)

func (Packet) RequiredSize

func (p Packet) RequiredSize() int

type Ping

type Ping struct {
	// Cookie represents a random value representing this ping request
	Cookie uint16
	// Period represents the current protocol period in the member that
	// generated this message.
	Period uint16
	// TargetIncarnation indicates the known incarnation of the node being
	// pinged in the current view of the local node
	TargetIncarnation uint16

	// Events contains a list of events observed by the node sending this ping.
	Events []Event
}

Ping represents a ping request to another cluster member.

func (Ping) Encode

func (p Ping) Encode(into []byte)

func (Ping) OpCode

func (p Ping) OpCode() OpCode

func (Ping) RequiredSize

func (p Ping) RequiredSize() int

type Pong

type Pong struct {
	// Ack indicates whether the target node accepted the ping payload. When set
	// to false, this indicates that the provided Ping.TargetIncarnation did not
	// correspond to the current node's incarnation, and was therefore ignored.
	// This is used to avoid nodes announcing suspects due to their own view
	// being outdated.
	Ack bool

	Cookie, Period uint16

	IsLastStateKnown     bool
	LastKnownEventKind   EventKind
	LastKnownIncarnation uint16
}

Pong represents a response for a Ping message.

func (Pong) Encode

func (p Pong) Encode(into []byte)

func (Pong) OpCode

func (p Pong) OpCode() OpCode

func (Pong) RequiredSize

func (p Pong) RequiredSize() int

type Suspect

type Suspect struct {
	Source      IP
	Subject     IP
	Incarnation uint16
}

Suspect represents the value of an EventSuspect, which indicates that a node Source could not reach a second node Subject, and started indirect Ping attempts.

func (*Suspect) Encode

func (s *Suspect) Encode(into []byte)

func (*Suspect) FromNode

func (s *Suspect) FromNode(n *Node)

func (*Suspect) GetIncarnation

func (s *Suspect) GetIncarnation() uint16

func (*Suspect) GetSubject

func (s *Suspect) GetSubject() IP

func (*Suspect) Invalidates

func (s *Suspect) Invalidates(current *Event) bool

func (*Suspect) Kind

func (s *Suspect) Kind() EventKind

func (*Suspect) RequiredSize

func (s *Suspect) RequiredSize() int

func (*Suspect) SetSource

func (s *Suspect) SetSource(source *IP)

func (*Suspect) SourceAddressKind

func (s *Suspect) SourceAddressKind() AddressKind

func (*Suspect) SubjectAddressKind

func (s *Suspect) SubjectAddressKind() AddressKind

type Sync

type Sync struct {
	Nodes []Node
	Mode  SyncMode
}

Sync represents a Sync request for another node. It contains all Node objects known by this (or the other) member.

func (Sync) Encode

func (s Sync) Encode(into []byte)

func (Sync) OpCode

func (s Sync) OpCode() OpCode

func (Sync) RequiredSize

func (s Sync) RequiredSize() int

type SyncMode

type SyncMode uint8
const (
	SyncModeFirstPhase   SyncMode = 0b00
	SyncModeSecondPhase  SyncMode = 0b01
	SyncModeBootstrap    SyncMode = 0b10
	SyncModeBootstrapAck SyncMode = 0b11
)

func (SyncMode) String

func (i SyncMode) String() string

type TCPPacket

type TCPPacket struct {
	Magic   uint16
	Version uint8
	Payload []byte
}

TCPPacket represents an opaque TCP message of an arbitrary length. This packet is a mere convenience to retain all parsing operations isolated in the networking package.

func EncTCPPkt

func EncTCPPkt(incarnation uint16, message Message, cryptoSealer func([]byte) ([]byte, error)) (*TCPPacket, error)

EncTCPPkt encodes a given Message into a TCPPacket, sealing it using the provided `cryptoSealer`. `incarnation` and `message` are handled verbatim by EncPkt before sealing.

func (TCPPacket) Encode

func (t TCPPacket) Encode(into []byte)

func (TCPPacket) RequiredSize

func (t TCPPacket) RequiredSize() int

type Wrap

type Wrap struct {
	Subject        IP
	Incarnation    uint16
	NewIncarnation uint16
}

Wrap represents the value of an EventWrap. It indicates that a given node Subject is about to have its incarnation number wrapped to a previous value, as a new interaction would overflow the size of the current numeric type.

func (*Wrap) Encode

func (w *Wrap) Encode(into []byte)

func (*Wrap) FromNode

func (w *Wrap) FromNode(n *Node)

func (*Wrap) GetIncarnation

func (w *Wrap) GetIncarnation() uint16

func (*Wrap) GetSubject

func (w *Wrap) GetSubject() IP

func (*Wrap) Invalidates

func (w *Wrap) Invalidates(current *Event) bool

func (*Wrap) Kind

func (w *Wrap) Kind() EventKind

func (*Wrap) RequiredSize

func (w *Wrap) RequiredSize() int

func (*Wrap) SourceAddressKind

func (w *Wrap) SourceAddressKind() AddressKind

func (*Wrap) SubjectAddressKind

func (w *Wrap) SubjectAddressKind() AddressKind

type Writer

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

Jump to

Keyboard shortcuts

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