safety

package
v0.11.0 Latest Latest
Warning

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

Go to latest
Published: Jun 8, 2026 License: MPL-2.0 Imports: 6 Imported by: 0

Documentation

Overview

Package safety provides end-to-end data protection and deterministic queuing primitives for safety-oriented DDS deployments.

E2EPublisher prepends an 18-byte protection header to every payload before writing. E2ESubscriber strips the header and validates CRC, sequence counter, and sample freshness on every received sample.

Wire format (little-endian, 18 bytes followed by original payload):

Bytes  0–1   DataID (uint16)
Bytes  2–3   SourceID (uint16)
Bytes  4–7   SequenceCounter (uint32, monotonically increasing per publisher)
Bytes  8–15  Timestamp (int64, Unix nanoseconds at time of Write)
Bytes 16–17  CRC-16/CCITT-FALSE over bytes 0–15 plus the original payload
Bytes 18+    Original payload

The CRC slot is treated as zero when computing the CRC.

Index

Constants

This section is empty.

Variables

View Source
var ErrQueueFull = errors.New("safety: queue full")

ErrQueueFull is returned by Enqueue when the DeterministicQueue has no remaining capacity.

Functions

This section is empty.

Types

type DeterministicQueue

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

DeterministicQueue is a bounded FIFO that decouples application writes from the underlying publisher. It contains the publisher's panic (converting it to an error on the Errors channel) and provides non-blocking back-pressure via ErrQueueFull.

Typical use:

q := safety.NewDeterministicQueue(pub, 128).Start()
defer q.Stop()

if err := q.Enqueue(payload); err != nil {
    // handle back-pressure
}

func NewDeterministicQueue

func NewDeterministicQueue(pub dds.Publisher, depth int) *DeterministicQueue

NewDeterministicQueue creates a queue with the given channel depth that drains into pub. Call Start to begin delivery. A depth of ≤ 0 uses 64.

func (*DeterministicQueue) Enqueue

func (q *DeterministicQueue) Enqueue(payload []byte) error

Enqueue adds payload to the queue without blocking. Returns ErrQueueFull if the queue is at capacity.

func (*DeterministicQueue) Errors

func (q *DeterministicQueue) Errors() <-chan error

Errors returns a channel that receives errors from the drain goroutine, including publisher errors and panics wrapped as errors.

func (*DeterministicQueue) Start

Start launches the drain goroutine. Returns q for chaining.

func (*DeterministicQueue) Stop

func (q *DeterministicQueue) Stop()

Stop signals the drain goroutine to exit and waits for it to finish. Safe to call more than once.

type E2EConfig

type E2EConfig struct {
	// DataID identifies the logical data element (0–65535).
	DataID uint16
	// SourceID identifies the sender (0–65535).
	SourceID uint16
	// MaxAge is the maximum permitted age of a received sample, measured from
	// the timestamp written by the publisher. Zero disables freshness checking.
	MaxAge time.Duration
}

E2EConfig configures end-to-end protection parameters shared by a publisher and subscriber pair.

type E2EError

type E2EError struct {
	Kind    E2EErrorKind
	Counter uint32
	Message string
}

E2EError is sent over the Errors channel when a safety check fails.

func (E2EError) Error

func (e E2EError) Error() string

type E2EErrorKind

type E2EErrorKind int

E2EErrorKind categorises safety check failures reported by E2ESubscriber.

const (
	// ErrCRCMismatch means the CRC in the frame header did not match.
	ErrCRCMismatch E2EErrorKind = iota
	// ErrSequenceGap means one or more sequence numbers were skipped.
	ErrSequenceGap
	// ErrStaleSample means the sample's timestamp is older than MaxAge.
	ErrStaleSample
	// ErrHeaderTooShort means the payload is shorter than the 18-byte header.
	ErrHeaderTooShort
)

type E2EPublisher

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

E2EPublisher wraps a dds.Publisher and prepends an E2E protection header to every Write payload. It satisfies dds.Publisher.

func NewE2EPublisher

func NewE2EPublisher(pub dds.Publisher, cfg E2EConfig) *E2EPublisher

NewE2EPublisher wraps pub with end-to-end protection configured by cfg.

func (*E2EPublisher) Close

func (p *E2EPublisher) Close() error

Close closes the underlying publisher.

func (*E2EPublisher) Write

func (p *E2EPublisher) Write(payload []byte) error

Write prepends an E2E header to payload and writes the frame to the underlying publisher.

type E2ESubscriber

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

E2ESubscriber wraps a dds.Subscriber, strips the E2E header from each received sample, and validates CRC, sequence counter, and freshness. Valid samples are forwarded to C(); failures are reported on Errors().

The background pump goroutine starts on construction and exits when Close is called or the underlying subscriber channel is closed.

func NewE2ESubscriber

func NewE2ESubscriber(sub dds.Subscriber, cfg E2EConfig) *E2ESubscriber

NewE2ESubscriber wraps sub with E2E validation using cfg.

func (*E2ESubscriber) C

func (s *E2ESubscriber) C() <-chan dds.Sample

C returns the channel that delivers validated, header-stripped samples. It satisfies dds.Subscriber.

func (*E2ESubscriber) Close

func (s *E2ESubscriber) Close() error

Close stops the pump goroutine and closes the underlying subscriber.

func (*E2ESubscriber) Errors

func (s *E2ESubscriber) Errors() <-chan E2EError

Errors returns a channel that receives E2EError values for every safety check failure. The channel is buffered (32); overflows are silently dropped.

Jump to

Keyboard shortcuts

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