ax25

package
v0.13.2 Latest Latest
Warning

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

Go to latest
Published: May 7, 2026 License: GPL-2.0 Imports: 3 Imported by: 0

Documentation

Overview

Package ax25 implements AX.25 v2.0 UI frame encode/decode.

Only Unnumbered Information (UI) frames are supported — the workhorse for APRS, digipeater, and beaconing. Connected-mode frames (I, RR, RNR, REJ, SABM, DISC, UA, DM, FRMR) are recognised by control-field value but not otherwise implemented; see Frame.IsUI.

Index

Constants

View Source
const (
	// ControlUI is the unnumbered-information control byte (poll/final=0).
	ControlUI = 0x03
	// ControlUIWithPF is UI with the poll/final bit set.
	ControlUIWithPF = 0x13

	// PIDNoLayer3 is the APRS-standard Protocol Identifier.
	PIDNoLayer3 = 0xF0
)

AX.25 control-field values.

View Source
const (
	PriorityBeacon     = 1 // scheduled beacons
	PriorityDigipeated = 2 // digipeater-repeated traffic
	PriorityClient     = 3 // KISS/AGW client-originated
	PriorityAX25Conn   = 4 // interactive AX.25 connected-mode (LAPB)
	PriorityIGateMsg   = 5 // iGate-delivered directed message
)

TX governor priority levels. Higher value = sent sooner.

These live in pkg/ax25 (a leaf package imported by every protocol package) so that submitters in pkg/kiss, pkg/agw, pkg/aprs, and future digipeater/iGate packages can reference the same values without importing pkg/txgovernor (which would create an import cycle).

pkg/txgovernor re-defines the same constants for its own API surface and asserts equality at init time; if these ever drift, the test in pkg/txgovernor will fail.

View Source
const MaxRepeaters = 8

MaxRepeaters is the AX.25 maximum number of digipeater addresses in the path.

Variables

This section is empty.

Functions

func EncodeAddressBlock added in v0.12.4

func EncodeAddressBlock(src, dst Address, path []Address, isCommand bool) ([]byte, error)

EncodeAddressBlock writes the AX.25 address header (dest, source, path) for both UI and connected-mode frames. isCommand selects v2.0 command-frame C-bit polarity (dest C set, source C clear).

Types

type Address

type Address struct {
	Call     string // 1..6 uppercase alphanumerics
	SSID     uint8  // 0..15
	Repeated bool   // H bit — only meaningful for digipeater path entries
}

An Address is a callsign + SSID pair, with AX.25 digipeater "has been repeated" (H) flag for path entries.

func ParseAddress

func ParseAddress(s string) (Address, error)

ParseAddress parses "CALL[-SSID][*]" into an Address. The trailing '*' sets Repeated.

func (Address) String

func (a Address) String() string

String renders "CALL[-SSID][*]" (trailing '*' if Repeated is set).

type AddressBlock added in v0.12.4

type AddressBlock struct {
	Source, Dest Address
	Path         []Address
	IsCommand    bool
	AddrLen      int
}

AddressBlock holds the parsed address header of an AX.25 frame (destination + source + digipeater path).

func DecodeAddressBlock added in v0.12.4

func DecodeAddressBlock(raw []byte) (AddressBlock, error)

DecodeAddressBlock parses dest+source+path from raw, returning the number of bytes consumed in AddrLen.

type Frame

type Frame struct {
	Dest    Address
	Source  Address
	Path    []Address // up to 8 digipeater addresses
	Control byte      // UI control byte (used iff ConnectedControl == nil)
	PID     byte
	Info    []byte

	// CommandResp encodes the C-bit layout: direwolf-style command = dest
	// C-bit set, source C-bit clear (AX.25 v2.0 "command" frame). The
	// default New* constructors produce a command frame.
	CommandResp bool

	// ConnectedControl, when non-empty, is the wire-encoded control
	// field for a connected-mode frame (1 byte mod-8 / 2 bytes
	// mod-128). UI Control is ignored when this field is set.
	ConnectedControl []byte

	// ConnectedHasInfo indicates that PID and Info should be appended
	// after ConnectedControl. True for I-frames and the v2.2 informational
	// U-frames (FRMR, XID, TEST); false for RR/RNR/REJ/SREJ/SABM/E,
	// DISC, UA, DM.
	ConnectedHasInfo bool
}

A Frame is a decoded AX.25 UI or connected-mode frame. The zero value is not a valid frame.

UI frames carry [Frame.Control] (single byte) plus PID/Info. Connected-mode frames (I, RR, RNR, REJ, SABM/E, DISC, UA, DM, FRMR, XID, TEST) populate [Frame.ConnectedControl] (1 byte mod-8, 2 bytes mod-128) and leave Control unused; PID and Info are only set when [Frame.ConnectedHasInfo] is true. pkg/ax25conn produces connected-mode Frames via [ax25conn.Frame.ToAX25Frame] so the txgovernor send path, hook surface, and dedup keying continue to observe a single Frame surface.

func Decode

func Decode(raw []byte) (*Frame, error)

Decode parses an AX.25 frame from raw bytes. Only UI frames have their info field populated; other control-field values parse the header and return a Frame with IsUI()==false and empty Info.

func NewUIFrame

func NewUIFrame(source, dest Address, path []Address, info []byte) (*Frame, error)

NewUIFrame constructs a v2.0-command UI frame with the given path and payload. PID defaults to 0xF0 (no-layer-3, APRS).

func (*Frame) DedupKey

func (f *Frame) DedupKey() string

DedupKey returns a string suitable as a map key for deduplication at the AX.25 frame level. Uses (dest + source + info) so identical content from the same source to the same destination collapses regardless of how the frame was routed or which digipeaters it traversed. This is the key the centralized TX governor uses to prevent the same frame being queued twice in rapid succession.

Call PathDedupKey instead when the path matters, e.g. the digipeater's own duplicate-suppression map where two copies of the same payload arriving over different geographic paths should be treated as distinct events.

func (*Frame) Encode

func (f *Frame) Encode() ([]byte, error)

Encode serialises f into a byte slice suitable for passing as the Data field of a TransmitFrame IPC message (no FCS — the modem appends it).

func (*Frame) IsConnectedMode added in v0.12.4

func (f *Frame) IsConnectedMode() bool

IsConnectedMode reports whether f represents a connected-mode (LAPB) frame produced by pkg/ax25conn rather than a UI frame.

func (*Frame) IsUI

func (f *Frame) IsUI() bool

IsUI reports whether the frame is an Unnumbered Information frame. Connected-mode control bytes (I, RR, RNR, REJ, SABM/E, DISC, UA, DM, FRMR, XID, TEST) return false.

func (*Frame) PathDedupKey

func (f *Frame) PathDedupKey() string

PathDedupKey returns a dedup key that includes the digipeater path. Used by the digipeater: two copies of the same payload heard via different unconsumed path slots are not the same observation for the purposes of digi suppression, because digi-ing them both could extend a packet's geographic reach legitimately. Only the call and SSID of each path element contribute; the repeated (H) bit is deliberately omitted so an unconsumed-then-consumed pair still dedups (the payload is the same; only the H-bit changed as we digi'd it).

func (*Frame) String

func (f *Frame) String() string

String renders a direwolf-style monitor line: "SRC>DEST[,DIGI*,...]:info".

Jump to

Keyboard shortcuts

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