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

stack

package
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: Oct 17, 2026 License: GPL-3.0 Imports: 5 Imported by: 0

Documentation

Overview

Package stack couples the link and transport layers to a byte stream.

A master and an outstation differ entirely at the application layer and barely at all below it: both frame fragments, both reassemble them, both answer link-layer requests. That shared plumbing lives here so neither session has to reimplement it, and so the two cannot drift apart.

A Stack is not safe for concurrent use, and is deliberately not made so. Sessions call it only from their own goroutine; their read goroutine hands raw octets across a channel rather than calling in directly. Locking the stack instead would make it possible to interleave a send with the processing of an inbound frame, and the link state machines are not interleavable — a frame count bit advanced from two places is a lost or duplicated fragment.

Index

Constants

View Source
const ReadChunk = link.MaxFrameSize

ReadChunk is the size a session's read goroutine should use.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	// LocalAddr and RemoteAddr are the link addresses of the two stations.
	LocalAddr  uint16
	RemoteAddr uint16
	// IsMaster sets the direction bit and selects which side answers what.
	IsMaster bool
	// SelfAddress accepts the discovery destination for outstations only.
	SelfAddress bool
	// UseConfirms enables link-layer confirmation. Over TCP this is normally
	// off, since the transport already guarantees ordered delivery; over
	// serial it is normally on.
	UseConfirms bool
	// MaxRetries is how many times a confirmed frame is retransmitted.
	MaxRetries int
	// MaxRxFragment caps a reassembled application fragment.
	MaxRxFragment int
}

Config parameterises a stack.

type Received

type Received struct {
	// Fragment is a completed application fragment. It aliases the stack's
	// reassembly buffer and is valid only for the duration of the callback.
	Fragment []byte
	// Source is the link address the fragment came from.
	Source uint16
	// Dest is the link address it was sent to, which may be a broadcast
	// address. An outstation must answer a broadcast without echoing it.
	Dest uint16
	// Broadcast reports whether Dest was a broadcast address.
	Broadcast bool
}

Received is what one completed fragment looks like.

type Stack

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

Stack owns the link and transport state for one connection.

It performs no I/O of its own and reads no clock: Send writes through a caller-supplied writer, Receive is fed octets the caller has already read, and link timeouts are reported by the caller through OnTimeout. That keeps the blocking, the goroutines and the timers in the session, where they can be cancelled.

func New

func New(cfg Config) *Stack

New returns a stack for one connection.

func (*Stack) Busy

func (s *Stack) Busy() bool

Busy reports whether a fragment is still being transmitted, either awaiting a confirmation or with segments still to send.

func (*Stack) OnTimeout

func (s *Stack) OnTimeout(w io.Writer) (failed bool, err error)

OnTimeout is called by the session when its link timer expires.

It retransmits the unacknowledged frame, or gives up once the retry budget is spent. The returned bool reports whether the transmission failed for good, which the session surfaces as a failed request rather than a silent stall.

func (*Stack) Pending

func (s *Stack) Pending() bool

Pending reports whether a confirmed frame is awaiting acknowledgement.

A session arms its link timer while this is true and calls Stack.OnTimeout when it fires. With confirmations disabled it is never true.

func (*Stack) Receive

func (s *Stack) Receive(w io.Writer, data []byte, fn func(Received)) error

Receive feeds received octets, calling fn for each completed application fragment.

Link-layer replies — acknowledgements, link status — are written to w as they are produced, and an acknowledgement of our own confirmed frame releases the next segment.

func (*Stack) Reset

func (s *Stack) Reset()

Reset clears all link and transport state, as when a connection is re-established. A fragment cannot span a connection and link state does not survive one.

func (*Stack) Send

func (s *Stack) Send(w io.Writer, fragment []byte) error

Send begins transmitting an application fragment.

With confirmations disabled every segment goes out immediately and the call completes the fragment. With them enabled only the first frame is sent; Stack.Pending then reports true until the peer acknowledges it, and the remaining segments follow as each acknowledgement arrives.

func (*Stack) SendLinkStatusRequest

func (s *Stack) SendLinkStatusRequest(w io.Writer) error

SendLinkStatusRequest sends a keep-alive.

An idle TCP connection tells you nothing: a peer that has gone away, or a firewall that has quietly dropped the flow, looks exactly like a peer with nothing to report. Asking for link status is how a session finds out before the next poll is due.

func (*Stack) SendTo

func (s *Stack) SendTo(w io.Writer, dest uint16, fragment []byte) error

SendTo frames a fragment addressed to a specific station, overriding the configured remote address.

An outstation needs this: it must answer whichever master addressed it, which is not necessarily the one in its configuration, and a broadcast request must be answered to the real source rather than to the broadcast address it arrived on.

func (*Stack) Stats

func (s *Stack) Stats() (link.Stats, transport.Stats)

Stats returns the link and transport counters.

Jump to

Keyboard shortcuts

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