exchange

package
v0.8.2 Latest Latest
Warning

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

Go to latest
Published: Oct 19, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

Documentation

Overview

Package exchange is the controller's message layer: the sessions and the exchanges of the initiator role over one UDP socket, with the Message Reliability Protocol (MRP) on every exchange. It is the port of matter.js packages/protocol/src/protocol/ExchangeManager.ts and MessageExchange.ts for the client role (ADR 0020, stage 1), and the layer the PASE and CASE clients of controller/handshake run on.

A Manager owns the socket's send side, the session table and the exchange table, and is fed every received datagram through Manager.HandleDatagram (a transport/udp Handler). A Session is either the unsecured session of a handshake (Manager.NewUnsecuredSession) or a secure PASE / CASE session (Manager.NewSecureSession) whose encryption is a secure/channel Session. An Exchange is one exchange this node initiated (Manager.Initiate): Exchange.Send transmits reliably and returns once the peer acknowledged, Exchange.Next waits for the peer's next message, Exchange.Close ends it.

Scope: UDP only and unicast only (no group sessions). An exchange a peer opens reaches a ProtocolHandler installed with Manager.SetProtocolHandler (ADR 0020, stage 3): on a secure session any protocol's but the Secure Channel's, whose CloseSession handling is built in as matter.js's StatusReportOnlySecureChannelProtocol; on an unsecured session the peer opens, a Sigma1 for the CASE responder, a PBKDFParamRequest being refused. A message no handler takes is acknowledged when it asks for an acknowledgement and otherwise dropped.

Index

Constants

View Source
const (
	// MaxTransmissions is the number of transmissions of one reliable
	// message, the first included. Mirrors matter.js
	// packages/protocol/src/protocol/MRP.ts:33 (MAX_TRANSMISSIONS = 5) at
	// 0ceb202d.
	MaxTransmissions = 5

	// StandaloneAckTimeout is how long a received reliable message waits
	// for an outbound message to piggyback its acknowledgement before a
	// standalone ack goes out. Mirrors matter.js MRP.ts:48
	// (STANDALONE_ACK_TIMEOUT = 200 ms), the delay of mrp.AckTracker.
	StandaloneAckTimeout = mrp.DefaultStandaloneAckDelay

	// DefaultExpectedProcessingTime is the peer's processing time an
	// exchange assumes when the caller states none. Mirrors matter.js
	// MRP.ts:55 (DEFAULT_EXPECTED_PROCESSING_TIME = 2 s).
	DefaultExpectedProcessingTime = 2 * time.Second

	// MaxPayloadSize is the largest message payload an exchange sends over
	// UDP: the 1232-byte UDP payload of an IPv6 minimum MTU less the Matter
	// message overhead (26 + 12 + 16). Mirrors matter.js
	// packages/protocol/src/protocol/MessageExchange.ts:156
	// (MATTER_MESSAGE_OVERHEAD), :435-439 (maxPayloadSize) and
	// packages/general/src/net/udp/UdpSocket.ts:12 (MAX_UDP_MESSAGE_SIZE).
	MaxPayloadSize = 1232 - (26 + 12 + 16)
)

MRP constants of the exchange layer.

View Source
const (
	FallbackIdleInterval             uint32 = 500  // ms, SessionIntervals.ts:46
	FallbackActiveInterval           uint32 = 300  // ms, SessionIntervals.ts:47
	FallbackActiveThreshold          uint16 = 4000 // ms, SessionIntervals.ts:48
	FallbackDataModelRevision        uint16 = 17   // SessionParameters.ts:125
	FallbackInteractionModelRevision uint16 = 11   // SessionParameters.ts:131
	FallbackMaxPathsPerInvoke        uint16 = 1    // SessionParameters.ts:145
)

Fallbacks for session parameters a peer did not report. Mirrors matter.js packages/protocol/src/session/SessionIntervals.ts:45-49 (the intervals) and SessionParameters.ts:118-153 (the rest) at 0ceb202d.

View Source
const MaxConcurrentExchangesPerSession = 30

MaxConcurrentExchangesPerSession is the number of open exchanges one secure session keeps; opening one more closes the least recently active one. Mirrors matter.js packages/protocol/src/protocol/ExchangeManager.ts:54 (MAXIMUM_CONCURRENT_OUTGOING_EXCHANGES_PER_SESSION = 30) and the eviction of :494-531 at 0ceb202d; the unsecured session is exempt (:511-514).

View Source
const UnsecuredSessionID uint16 = 0

UnsecuredSessionID is the session id of the unsecured session. Mirrors matter.js packages/protocol/src/session/UnsecuredSession.ts:18 (UNICAST_UNSECURE_SESSION_ID) at 0ceb202d.

Variables

View Source
var (
	// ErrTransient is the class of every error after which the peer may
	// still be present but cannot be reached right now — matter.js
	// TransientPeerCommunicationError (PeerCommunicationError.ts:19).
	// [PeerUnresponsiveError], [PeerMessageMissingError] and
	// [StatusReportError] are transient.
	ErrTransient = errors.New("exchange: transient peer communication error")

	// ErrNetwork wraps a failure of the socket to send — matter.js
	// NetworkError.
	ErrNetwork = errors.New("exchange: network error")

	// ErrRetransmissionLimit is matter.js RetransmissionLimitReachedError
	// (packages/protocol/src/protocol/errors.ts:17, deprecated there and thrown by no exchange at
	// 0ceb202d). It is kept so the handshakes' "do not report an error to
	// a peer we cannot reach" rule names the same three classes matter.js
	// names (PaseClient.ts:101, CaseClient.ts:89).
	ErrRetransmissionLimit = errors.New("exchange: retransmission limit reached")

	// ErrFlow is a call the exchange's state forbids — a second send
	// while the previous message is unacknowledged (MessageExchange.ts:669-673),
	// a message that fails to acknowledge our pending one
	// (MessageExchange.ts:493-504) — matter.js MatterFlowError.
	ErrFlow = errors.New("exchange: flow error")

	// ErrExchangeClosed is returned by a call on a closed exchange
	// (MessageExchange.ts:606-608, ClosedError).
	ErrExchangeClosed = errors.New("exchange: exchange closed")

	// ErrSessionClosed is returned by a call on a closed session
	// (matter.js SessionClosedError, protocol/errors.ts:35).
	ErrSessionClosed = errors.New("exchange: session closed")

	// ErrUnexpectedMessage is a reply the exchange did not expect — an
	// ack-only send answered with data (MessageExchange.ts:815-817).
	ErrUnexpectedMessage = errors.New("exchange: unexpected message")

	// ErrNoSessionID is returned when every session id is taken and no
	// session can be closed to free one (SessionManager.ts:515-523).
	ErrNoSessionID = errors.New("exchange: no session id available")
)

Errors of the exchange layer. The classes follow matter.js packages/protocol/src/peer/PeerCommunicationError.ts and packages/protocol/src/protocol/errors.ts at 0ceb202d; a caller tests them with errors.Is.

Functions

func CheckStatusReport

func CheckStatusReport(payload []byte) error

CheckStatusReport returns a *StatusReportError unless payload is a StatusReport with general code Success and protocol code Success (SESSION_ESTABLISHMENT_SUCCESS) — SecureChannelMessenger.ts:234-259 throwIfErrorStatusReport. A body too short to decode is an ErrUnexpectedMessage.

func DefaultLocalParameters

func DefaultLocalParameters() sessionparams.Parameters

DefaultLocalParameters is the session parameters a controller sends when its host chose none: matter.js SessionParameters.defaults (SessionParameters.ts:158-164), the fallbacks with this module's data-model revision, interaction-model revision and specification version.

func MaxPeerResponseTime

func MaxPeerResponseTime(peer *Intervals, peerActive bool, local Intervals, expectedProcessingTime time.Duration) time.Duration

MaxPeerResponseTime is how long an exchange waits for the peer's next message over UDP with MRP: our own worst-case retransmission time (local intervals, assumed active), the expected processing time and a 5 s buffer, plus — when peer is not nil — the peer's worst-case retransmission time back to us. Mirrors matter.js MRP.ts:79-120 (maxPeerResponseTimeOf, the "udp" case).

Exchange.Next passes no peer intervals: matter.js MessageExchange.ts:840-847 calls calculateMaximumPeerResponseTime with includeMaximumSendingTime undefined, and MessageChannel.ts:224-226 then omits the peer direction.

func Overlay

Overlay returns base with every field over states replacing it — the object spread `{...base, ...over}` matter.js uses to combine parameter sets (PaseClient.ts:168-171, CaseClient.ts:184-188).

func PeerParameters

func PeerParameters(reported *sessionparams.Parameters) sessionparams.Parameters

PeerParameters is the parameters a session assumes for its peer: the fallbacks overlaid by what the peer reported (nil reported nothing), with TCP cleared for a peer below Matter 1.5, MaxTCPMessageSize only when TCP remains, and a MaxPathsPerInvoke of 0 taking the fallback. Mirrors matter.js SessionParameters.ts:42-81 (the SessionParameters factory).

func ReliableMaxPeerResponseTime added in v0.7.0

func ReliableMaxPeerResponseTime(expectedProcessingTime time.Duration) time.Duration

ReliableMaxPeerResponseTime is how long an exchange waits for the peer's next message on a reliable channel without MRP: 30 s, or the expected processing time when longer, plus the 5 s buffer. Mirrors matter.js MRP.ts:111-113 (the "ble" case; the "tcp" case at :90-92 is the same).

func RetransmissionInterval

func RetransmissionInterval(n int, p Intervals, peerActive bool, rand01 float64) time.Duration

RetransmissionInterval is the wait after transmission number n (0 is the first transmission) of a reliable message to a peer with intervals p: the peer's active interval while it is active, its idle interval otherwise, grown by the §4.12.2.1 backoff and jittered by rand01 (a value in [0, 1); 1 gives the maximum), floored to whole milliseconds.

Mirrors matter.js packages/protocol/src/protocol/MRP.ts:162-190 (retransmissionIntervalOf) at 0ceb202d with additionalDelay and fixedBackoff zero — the controller has no network profile — through transport/mrp.BackoffDuration, the same formula.

Types

type Clock

type Clock = clock.Clock

Clock is the time source of a Manager: the current time and timers. The default is the system clock; a test supplies its own (github.com/SukramJ/go-fabric/clock/clocktest.Fake) to step the retransmission and acknowledgement timers deterministically.

Clock is the module's one time port, clock.Clock; the alias keeps every existing reference to exchange.Clock compiling.

type Config

type Config struct {
	// LocalParameters are our session parameters: sent in the handshakes
	// and the timing of our own retransmissions. Nil is
	// [DefaultLocalParameters].
	LocalParameters *sessionparams.Parameters
	// Clock is the time source; nil is [SystemClock].
	Clock Clock
	// Rand returns the MRP jitter draw in [0, 1); nil is math/rand/v2.Float64.
	Rand func() float64
	// Logger receives debug diagnostics; nil discards them.
	Logger *slog.Logger
	// PeerLost is called when a send or a wait on an exchange of a secure
	// session fails in a way that shows the peer is gone — matter.js
	// MessageExchangeContext.peerLost (ExchangeManager.ts:556-579), fired
	// from MessageExchange.ts:613-621 and :822-832. Nil ignores it.
	PeerLost func(s *Session, cause error)
	// Reliable marks the manager's carrier as reliable (BTP): its sessions
	// do not use MRP — no acknowledgement requested, none sent, no
	// retransmission — and a wait for the peer is the reliable channel's.
	// Mirrors matter.js packages/protocol/src/session/Session.ts:355-356
	// (`usesMrp = supportsMRP && !channel?.isReliable`) for a manager whose
	// one channel is a BleChannel (packages/protocol/src/ble/Ble.ts:38).
	Reliable bool
}

Config configures a Manager.

type Conn

type Conn interface {
	Send(dst *net.UDPAddr, payload []byte) error
}

Conn is the send side of the socket a Manager uses. A *transport/udp.Listener satisfies it; its Serve handler is Manager.HandleDatagram.

type Exchange

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

Exchange is one exchange this node initiated. Send and Next are not meant for concurrent use with each other on one exchange (an exchange is one conversation), but every method is safe to call from any goroutine.

func (*Exchange) Abort

func (x *Exchange) Abort(cause error)

Abort closes the exchange at once with cause: an acknowledgement still owed goes out, nothing is waited for, and further calls fail with cause — matter.js MessageExchange.ts:1053-1105 (close with a cause).

func (*Exchange) Close

func (x *Exchange) Close()

Close ends the exchange gracefully — matter.js MessageExchange.ts:1053-1130 (close without a cause): an acknowledgement still owed goes out at once; with no message of ours unacknowledged the exchange closes now, otherwise it stays open for the maximum time our remaining transmissions can take, so a late acknowledgement is still taken, and closes then. An exchange that never sent closes at once. Close returns without waiting; Exchange.Done reports the end. It is idempotent.

func (*Exchange) ConsiderClosed

func (x *Exchange) ConsiderClosed() bool

ConsiderClosed reports whether the exchange counts as closed: closed, or — for an exchange we initiated — closing. It is matter.js MessageExchange.considerClosed (MessageExchange.ts:376-378), which a CASE responder reads before its error report (CaseServer.ts:82-86).

func (*Exchange) Done

func (x *Exchange) Done() <-chan struct{}

Done is closed once the exchange is closed and left the manager.

func (*Exchange) HasUnackedMessage

func (x *Exchange) HasUnackedMessage() bool

HasUnackedMessage reports whether a message we sent still waits for its acknowledgement — matter.js MessageExchange.ts:415-422. The exchange cannot send again in that state, so a handshake skips its best-effort error report.

func (*Exchange) ID

func (x *Exchange) ID() uint16

ID is the exchange id.

func (*Exchange) Next

func (x *Exchange) Next(ctx context.Context, opts ReceiveOptions) (*Message, error)

Next waits for the peer's next message on the exchange — matter.js MessageExchange.ts:822-860. The wait is opts.Timeout, or MaxPeerResponseTime of our own intervals and the expected processing time; on expiry it is a *PeerMessageMissingError, which reports the peer lost when nothing was received on the exchange. On a closed session the wait is unbounded but for ctx.

func (*Exchange) RetransmissionCount

func (x *Exchange) RetransmissionCount() int

RetransmissionCount is the number of retransmissions of the message the exchange sent last, reset by a new send and by its acknowledgement — matter.js MessageExchange.ts:410-413 (retransmissionCount): the counter of :263, reset at :508 (ack), :611 (send) and :786 (first transmission), incremented at :886 and taken back at :907 when only the final wait remains.

func (*Exchange) RetransmissionRestartSaving

func (x *Exchange) RetransmissionRestartSaving() time.Duration

RetransmissionRestartSaving is how much restarting the exchange — a fresh exchange whose first transmission waits the base backoff — would shorten the wait until the next (re)transmission: the interval of the retransmission timer armed last minus the backoff of transmission 0, never negative, and 0 before the exchange armed a timer. Mirrors matter.js MessageExchange.ts:1258-1266 (retransmissionRestartSaving), which reads the last timer's interval whether or not it still runs.

func (*Exchange) Send

func (x *Exchange) Send(ctx context.Context, opcode uint8, payload []byte, opts SendOptions) error

Send sends one message on the exchange and, when it travels reliably, returns once the peer acknowledged it. Mirrors matter.js MessageExchange.ts:605-820 (send, #send) at 0ceb202d:

  • a closed exchange refuses (:606-608);
  • the message asks for an acknowledgement unless SuppressAck (:660); a StatusReport travels on the Secure Channel protocol whatever the exchange's protocol (:662-665);
  • a send while the previous message is unacknowledged is an ErrFlow (:669-673);
  • the acknowledgement owed for the last received message rides along, and its standalone-ack timer stops (:679-686);
  • the message is retransmitted on the MRP schedule until acknowledged; after the last transmission and the final wait the send fails with a *PeerUnresponsiveError (:752-766, :879-966);
  • a failure with nothing received on the exchange that shows the peer gone reports it to the manager's PeerLost hook (:613-638).

A ctx already done sends nothing; a ctx done while waiting for the acknowledgement stops the retransmissions and leaves the message unacknowledged (:793-805). Both return ctx's error.

func (*Exchange) Session

func (x *Exchange) Session() *Session

Session is the session the exchange runs on.

type Intervals

type Intervals struct {
	// Idle is SESSION_IDLE_INTERVAL: the retry base while the node is idle.
	Idle time.Duration
	// Active is SESSION_ACTIVE_INTERVAL: the retry base while it is active.
	Active time.Duration
	// ActiveThreshold is SESSION_ACTIVE_THRESHOLD: how long after its last
	// message the node counts as active.
	ActiveThreshold time.Duration
}

Intervals are the MRP timing parameters of one side of a session.

func IntervalsOf

func IntervalsOf(p sessionparams.Parameters) Intervals

IntervalsOf is the MRP timing of p, the fallback for every interval p does not state (SessionIntervals.ts:36-42).

type Manager

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

Manager is the controller's exchange manager: one socket, the session table, the exchange table and the receive path. It is safe for concurrent use.

func NewManager

func NewManager(conn Conn, cfg Config) (*Manager, error)

NewManager returns a manager that sends on conn.

func (*Manager) AllocateSessionID

func (m *Manager) AllocateSessionID(ctx context.Context) (uint16, error)

AllocateSessionID returns the next free local session id for a PASE or CASE session: the cursor's next id that no session holds, cycling through 1..0xFFFF; when every id is taken the least recently used session is closed (the peer is told) and its id reused. Mirrors matter.js SessionManager.ts:504-557 (getNextAvailableSessionId, findOldestInactiveSession, #takeSessionId).

func (*Manager) Close

func (m *Manager) Close()

Close closes every exchange and session without telling the peers. It is idempotent; the manager accepts no new session afterwards.

func (*Manager) CloseSession

func (m *Manager) CloseSession(ctx context.Context, s *Session)

CloseSession ends a session: a secure session whose peer is not lost (NodeSession.ts:389-395) first sends CloseSession on a fresh exchange — a StatusReport (Success, CloseSession) without an acknowledgement request — then is dropped. Mirrors matter.js ExchangeManager.ts:716-726 (#sendCloseSession) and SecureChannelMessenger.ts:193-195 (sendCloseSession, suppressAck). A failure to send is logged, never returned: the session is gone either way.

func (*Manager) HandleDatagram

func (m *Manager) HandleDatagram(buf []byte, src *net.UDPAddr)

HandleDatagram processes one received datagram; it is the transport/udp Handler of the controller's socket. Mirrors matter.js ExchangeManager.ts:220-475 (#receiveMessage) for unicast messages: a message for an unknown session is dropped, the counter goes through the session's reception window (a duplicate still reaches its exchange, which acknowledges it), every decoded message marks the peer active, and a message no exchange of ours accepts is acknowledged when it asks for it and dropped otherwise.

func (*Manager) HandlePeerLoss

func (m *Manager) HandlePeerLoss(peer PeerAddress, cause error, asOf time.Time)

HandlePeerLoss gives up every secure session with peer created before asOf (a zero asOf: all of them) — each as Session.HandlePeerLoss does. Mirrors matter.js SessionManager.ts:636-638 (handlePeerLoss, asOf defaulting to now) and :677-696 (#handlePeerLoss: a session created at or after asOf is kept).

func (*Manager) Initiate

func (m *Manager) Initiate(s *Session, protocol uint16, opts Options) (*Exchange, error)

Initiate opens an exchange on s for protocol — matter.js ExchangeManager.ts:145-156 (initiateExchangeForSession): the exchange id is the next value of a counter that starts at random and wraps at 0xFFFF (:729-743), and the exchange is indexed apart from received ones.

func (*Manager) LocalParameters

func (m *Manager) LocalParameters() sessionparams.Parameters

LocalParameters is our session parameters.

func (*Manager) NewSecureSession

func (m *Manager) NewSecureSession(cfg SecureSessionConfig) (*Session, error)

NewSecureSession registers the secure session a handshake established. It counts the peer as active from the start (NodeSession.ts:119).

func (*Manager) NewUnsecuredSession

func (m *Manager) NewUnsecuredSession(addr *net.UDPAddr, peer *sessionparams.Parameters) (*Session, error)

NewUnsecuredSession opens the unsecured session of a handshake with the peer at addr. peer is what is known of the peer's session parameters (from its DNS-SD record), nil for none. Our side is the initiator: the session draws a random ephemeral node id, sends with the global unencrypted counter and counts the peer as idle until it answers — matter.js SessionManager.ts:418-458 (createUnsecuredSession) and UnsecuredSession.ts:26-34.

func (*Manager) Reliable added in v0.7.0

func (m *Manager) Reliable() bool

Reliable reports whether the manager's carrier is reliable (Config.Reliable).

func (*Manager) Session

func (m *Manager) Session(id uint16) *Session

Session returns the secure session with local id id, nil for none.

func (*Manager) SessionsFor

func (m *Manager) SessionsFor(peer PeerAddress) []*Session

SessionsFor returns the open secure sessions with peer — matter.js SessionManager.sessionsFor.

func (*Manager) SetProtocolHandler

func (m *Manager) SetProtocolHandler(protocol uint16, h ProtocolHandler)

SetProtocolHandler installs h for the exchanges the peer opens with protocol — matter.js ExchangeManager.addProtocolHandler, consulted for the first message of an exchange at ExchangeManager.ts:391-440. A nil h removes it. The Secure Channel protocol is special:

  • on a secure session its handler stays the built-in one (the StatusReport-only handler of SecureChannelProtocol.ts:30-88), h is not consulted;
  • on an unsecured session h receives a Sigma1 — matter.js SecureChannelProtocol.ts:146-148 hands it to the CaseServer — and a PBKDFParamRequest is refused with InvalidParam, the controller having no PASE server (:129-137).

Every other protocol's handler runs for the exchanges opened on a secure session only, as matter.js's InteractionServer and ClientSubscriptionHandler require (requiresSecureSession, ExchangeManager.ts:393-405). A message no handler takes is acknowledged when it asks for it and dropped (:441-473).

type Message

type Message struct {
	// Counter is the message counter of the packet header.
	Counter uint32
	// ProtocolID and Opcode name the message.
	ProtocolID uint16
	Opcode     uint8
	// ExchangeID is the exchange the message belongs to.
	ExchangeID uint16
	// Initiator is the sender's I flag.
	Initiator bool
	// RequiresAck is the R flag; HasAck and AckCounter the piggybacked
	// acknowledgement.
	RequiresAck bool
	HasAck      bool
	AckCounter  uint32
	// Payload is the application payload.
	Payload []byte
}

Message is one message received on an exchange.

type Options

type Options struct {
	// SuppressPeerLoss waives the peer-loss report for this exchange —
	// matter.js MessageExchange.Options.suppressPeerLoss
	// (MessageExchange.ts:1272-1273).
	SuppressPeerLoss bool

	// OnSend is called before every transmission of a message on the
	// exchange with its retransmission number: 0 for a first
	// transmission (a standalone ack included), n for the n-th
	// retransmission — matter.js MessageExchange.Options.onSend
	// (:1240-1243), called at :768 and :943. It runs on the sending
	// goroutine, for a first transmission with the exchange locked, so it
	// must not block for long or call back into the exchange.
	OnSend func(retransmission int)

	// AddressOverride sends the exchange's messages to this address instead
	// of the session's, leaving the session's address and its other
	// exchanges alone — matter.js MessageExchange.Options.addressOverride
	// (:1266-1270), stored at :297 and used for every transmission (:488,
	// :771-774, :953). Nil sends to the session's address.
	AddressOverride *net.UDPAddr

	// OnReceive is called for every message the exchange takes, a
	// duplicate and a standalone ack included — matter.js
	// MessageExchange.Options.onReceive (:1245-1248), called at :469
	// after the protocol check.
	OnReceive func()
}

Options configures Manager.Initiate — matter.js MessageExchange.Options (MessageExchange.ts:1239-1274).

type PeerAddress

type PeerAddress struct {
	FabricIndex uint8
	NodeID      uint64
}

PeerAddress names a peer on one of our fabrics: our fabric index and the peer's operational node id — matter.js PeerAddress (packages/protocol/src/peer/PeerAddress.ts); handshake.PeerAddress and the peer package use this type.

type PeerInitiatedCloseError

type PeerInitiatedCloseError struct{}

PeerInitiatedCloseError is the cause a session ends with when the peer closed it with a CloseSession StatusReport — matter.js PeerInitiatedCloseError (PeerCommunicationError.ts:71-75), raised by NodeSession.handlePeerClose (NodeSession.ts:305-309). It is transient.

func (*PeerInitiatedCloseError) Error

func (*PeerInitiatedCloseError) Is

func (*PeerInitiatedCloseError) Is(target error) bool

Is makes the error match ErrTransient.

type PeerMessageMissingError

type PeerMessageMissingError struct {
	// Timeout is the wait that expired.
	Timeout time.Duration
}

PeerMessageMissingError is an expected message that did not arrive on the exchange before the timeout — matter.js PeerMessageMissingError (PeerCommunicationError.ts:57), raised by MessageExchange.ts:854-856.

func (*PeerMessageMissingError) Error

func (e *PeerMessageMissingError) Error() string

func (*PeerMessageMissingError) Is

func (e *PeerMessageMissingError) Is(target error) bool

Is makes the error match ErrTransient and a *PeerUnresponsiveError target, as the matter.js class extends PeerUnresponsiveError.

type PeerUnresponsiveError

type PeerUnresponsiveError struct {
	// Waited is how long the exchange waited for the acknowledgement.
	Waited time.Duration
}

PeerUnresponsiveError is a reliable message the peer never acknowledged within MaxTransmissions transmissions and the final wait — matter.js PeerUnresponsiveError (PeerCommunicationError.ts:40-46), raised by MessageExchange.ts:763-765.

func (*PeerUnresponsiveError) Error

func (e *PeerUnresponsiveError) Error() string

func (*PeerUnresponsiveError) Is

func (e *PeerUnresponsiveError) Is(target error) bool

Is makes the error match ErrTransient.

type ProtocolHandler

type ProtocolHandler func(x *Exchange, first *Message)

ProtocolHandler handles an exchange the peer opened: x is the new exchange, first its first message, already taken by x — acknowledged as x acknowledges any message, and not returned by Exchange.Next, which waits for the message after it. It is matter.js ProtocolHandler.onNewExchange (packages/protocol/src/protocol/ProtocolHandler.ts:22-23 at 0ceb202d). It runs on a goroutine of its own, one per exchange, so the receive path never waits for it; the exchange is closed when it returns, if the handler did not close it.

type ReceiveOptions

type ReceiveOptions struct {
	// Timeout overrides the computed wait; 0 computes it from
	// [MaxPeerResponseTime].
	Timeout time.Duration
	// ExpectedProcessingTime enters the computed wait; 0 is
	// [DefaultExpectedProcessingTime].
	ExpectedProcessingTime time.Duration
	// SuppressPeerLoss waives the peer-loss report for this wait.
	SuppressPeerLoss bool
}

ReceiveOptions configures Exchange.Next — matter.js ExchangeReceiveOptions (MessageExchange.ts:134-148).

type SecureSessionConfig

type SecureSessionConfig struct {
	// ID is the local session id ([Manager.AllocateSessionID]).
	ID uint16
	// Addr is the peer's address.
	Addr *net.UDPAddr
	// Channel carries the keys, the node ids and the peer's session id.
	Channel channel.Config
	// PeerParameters is the peer's parameters: the fallbacks overlaid by
	// what it reported (SessionParameters.ts:42-81).
	PeerParameters sessionparams.Parameters
	// ReportedParameters is what the peer reported, nil for nothing.
	ReportedParameters *sessionparams.Parameters
	// CaseAuthenticatedTags are the session's CATs (CASE only).
	CaseAuthenticatedTags []uint32
	// AttestationChallenge is the third 16 bytes of the session keys.
	AttestationChallenge []byte
	// SuppressPeerLoss keeps the session open when an exchange fails
	// instead of reporting the peer lost — matter.js NodeSession
	// suppressPeerLoss (NodeSession.ts:316-318), set for the PASE session
	// of a commissioning.
	SuppressPeerLoss bool
	// Resumed marks a session from Sigma2_Resume.
	Resumed bool
	// FabricIndex is our fabric index of a CASE session, 0 for PASE: with
	// the channel's peer node id it is the session's peer address
	// (NodeSession.ts:408-413), the key of [Manager.HandlePeerLoss].
	FabricIndex uint8
}

SecureSessionConfig describes a session a handshake established.

type SendOptions

type SendOptions struct {
	// ExpectAckOnly makes a reply that carries data in place of a
	// standalone ack an [ErrUnexpectedMessage].
	ExpectAckOnly bool
	// ExpectedProcessingTime is the peer's processing time for the final
	// wait after the last retransmission; 0 is
	// [DefaultExpectedProcessingTime].
	ExpectedProcessingTime time.Duration
	// SuppressAck sends without requesting an acknowledgement (a
	// CloseSession or Busy StatusReport).
	SuppressAck bool
	// DisableMRP sends once, without retransmission and without waiting
	// for the acknowledgement.
	DisableMRP bool
	// MaxRetransmissions caps the transmissions; 0 is [MaxTransmissions],
	// a negative value is unlimited.
	MaxRetransmissions int
	// MaxRetransmissionTime caps each backoff, never below the peer's idle
	// interval; 0 is no cap.
	MaxRetransmissionTime time.Duration
	// InitialRetransmissionTime is added to every backoff.
	InitialRetransmissionTime time.Duration
	// SuppressPeerLoss waives the peer-loss report for this send.
	SuppressPeerLoss bool
	// AckWaitAbort, once closed, ends only the waits for the
	// acknowledgement and for retransmissions: the message is still
	// transmitted once, even when it closed before, and Send then returns
	// nil; the message stays unacknowledged for [Exchange.Close]. ctx —
	// matter.js's abort — still stops the transmission. Mirrors matter.js
	// ExchangeSendOptions.ackWaitAbort (MessageExchange.ts:125-130).
	AckWaitAbort <-chan struct{}
}

SendOptions configures Exchange.Send — matter.js ExchangeSendOptions (MessageExchange.ts:82-132).

type Session

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

Session is one session of the controller with a peer: the unsecured session a PASE or CASE handshake runs on, or a secure session the handshake established. It is safe for concurrent use.

func (*Session) ActiveTimestamp

func (s *Session) ActiveTimestamp() time.Time

ActiveTimestamp is the time of the last message received from the peer on the session — matter.js Session.activeTimestamp (session/Session.ts:61-65, updated by notifyActivity :141-147), the order of Peer.newestSession (peer/Peer.ts:581-601). A secure session starts at its creation time (Session.ts:119-121 with NodeSession.ts:119); the unsecured session is zero until the peer's first message.

func (*Session) Addr

func (s *Session) Addr() *net.UDPAddr

Addr is the peer's UDP address.

func (*Session) AttestationChallenge

func (s *Session) AttestationChallenge() []byte

AttestationChallenge is the attestation challenge the session keys yielded (the third 16 bytes of the key schedule; NodeSession.ts:88).

func (*Session) CaseAuthenticatedTags

func (s *Session) CaseAuthenticatedTags() []uint32

CaseAuthenticatedTags are the session's CASE Authenticated Tags (nil on PASE) — matter.js NodeSession caseAuthenticatedTags.

func (*Session) Close

func (s *Session) Close()

Close drops the session without telling the peer: its exchanges are closed with ErrSessionClosed, it leaves the manager's tables and its keys are dropped. Manager.CloseSession tells the peer first. It is idempotent.

func (*Session) Closing

func (s *Session) Closing() <-chan struct{}

Closing is closed once the session begins to close — Session.Close, Manager.CloseSession or a peer loss — matter.js Session.closing (Session.ts:70, emitted at :299), which a peer watches to drop the session (Peer.ts:169-174).

func (*Session) CreatedAt

func (s *Session) CreatedAt() time.Time

CreatedAt is when the session was established — matter.js Session.createdAt, the cutoff SessionManager.#handlePeerLoss compares (SessionManager.ts:690-692 at 0ceb202d).

func (*Session) FabricIndex

func (s *Session) FabricIndex() uint8

FabricIndex is our fabric index of a CASE session, 0 on the unsecured and on a PASE session — the fabric half of matter.js NodeSession.peerAddress (NodeSession.ts:408-413).

func (*Session) HandlePeerLoss

func (s *Session) HandlePeerLoss(cause error)

HandlePeerLoss gives the session up because the peer is gone: it is marked lost, the manager's PeerLost hook is called, every exchange on it is aborted with cause, and it is closed without a CloseSession on the wire. Mirrors matter.js NodeSession.ts:311-314 (handlePeerLoss) and :349-352 with Session.ts:318-331 (initiateForceClose). It is a no-op on a session already closed or lost.

func (*Session) ID

func (s *Session) ID() uint16

ID is the local session id: UnsecuredSessionID for the unsecured session, the id the peer addresses its messages to otherwise.

func (*Session) IsClosed

func (s *Session) IsClosed() bool

IsClosed reports whether the session was closed.

func (*Session) IsInbound

func (s *Session) IsInbound() bool

IsInbound reports whether the session is an unsecured session the peer opened with an initiating message — the session a CASE responder runs on (matter.js ExchangeManager.ts:261-264).

func (*Session) IsPeerActive

func (s *Session) IsPeerActive() bool

IsPeerActive reports whether the peer sent a message within its active threshold — matter.js Session.ts:149-151. The unsecured session of an initiator starts idle (UnsecuredSession.ts:30), a secure one active (NodeSession.ts:119).

func (*Session) IsPeerLost

func (s *Session) IsPeerLost() bool

IsPeerLost reports whether the session was given up because the peer is gone or closed it — matter.js NodeSession.isPeerLost (NodeSession.ts:320-322). A lost session is closing: no CloseSession goes to the peer.

func (*Session) IsSecure

func (s *Session) IsSecure() bool

IsSecure reports whether the session is encrypted (PASE or CASE).

func (*Session) NodeID

func (s *Session) NodeID() uint64

NodeID is our node id on the session: the ephemeral initiator node id on an unsecured session we opened, the operational node id on a CASE session and 0 on a PASE session and on an unsecured session the peer opened.

func (*Session) Parameters

func (s *Session) Parameters() sessionparams.Parameters

Parameters is the peer's session parameters as the session uses them: the fallbacks overlaid by what the peer reported — matter.js Session.ts:204-227 (parameters).

func (*Session) PeerNodeID

func (s *Session) PeerNodeID() uint64

PeerNodeID is the peer's operational node id: 0 on the unsecured and on a PASE session.

func (*Session) PeerSessionID

func (s *Session) PeerSessionID() uint16

PeerSessionID is the peer's session id for this session.

func (*Session) ReportedParameters

func (s *Session) ReportedParameters() *sessionparams.Parameters

ReportedParameters is what the peer reported in the handshake, nil when it reported nothing — matter.js NodeSession reportedSessionParameters.

func (*Session) Resumed

func (s *Session) Resumed() bool

Resumed reports that a CASE session came from Sigma2_Resume.

func (*Session) SetAddr

func (s *Session) SetAddr(addr *net.UDPAddr)

SetAddr moves the session to the peer's address addr: every later transmission on the session goes there, an exchange with an address override aside — matter.js `session.channel.networkAddress = address`, the in-place migration of PeerAddressMonitor.ts:243 and :170 (packages/protocol/src/peer/, 0ceb202d). A nil addr is ignored.

func (*Session) SetTimingParameters

func (s *Session) SetTimingParameters(p sessionparams.Parameters)

SetTimingParameters replaces the peer's MRP intervals with those p states, the fallback for each one it does not — matter.js Session.ts:249-254 (set timingParameters), which the handshakes call when the responder's parameters arrive (PaseClient.ts:163-165, CaseClient.ts:245-247).

func (*Session) UsesMRP added in v0.7.0

func (s *Session) UsesMRP() bool

UsesMRP reports whether the session runs MRP: not over a reliable carrier (matter.js Session.ts:355-356).

type StatusReport

type StatusReport struct {
	GeneralCode  uint16
	ProtocolID   uint32
	ProtocolCode uint16
	ProtocolData []byte
}

StatusReport is a Secure Channel StatusReport body: general code, protocol id, protocol code and optional protocol data, little-endian — the layout transport/mrp.EncodeStatusReport writes.

func DecodeStatusReport

func DecodeStatusReport(payload []byte) (StatusReport, bool)

DecodeStatusReport splits a StatusReport body. Mirrors matter.js packages/protocol/src/protocol/ProtocolStatusMessage.ts:50-66 (decodeInternal) at 0ceb202d, which SecureChannelStatusMessageSchema.ts:14 instantiates for the Secure Channel; ProtocolID carries the vendor id in its upper 16 bits as on the wire. ok is false for a body shorter than 8 bytes.

func (StatusReport) Encode

func (r StatusReport) Encode() []byte

Encode is the wire body of r.

type StatusReportError

type StatusReportError struct {
	Report StatusReport
}

StatusReportError is a StatusReport the peer answered with that is not Success — matter.js ChannelStatusResponseError (SecureChannelMessenger.ts:32-52, thrown at :234-259). It is transient.

func (*StatusReportError) Error

func (e *StatusReportError) Error() string

func (*StatusReportError) Is

func (e *StatusReportError) Is(target error) bool

Is makes the error match ErrTransient.

type SystemClock

type SystemClock = clock.System

SystemClock is the Clock of the time package; it is clock.System.

type Timer

type Timer = clock.Timer

Timer is a timer [Clock.AfterFunc] started; it is clock.Timer.

type UnexpectedMessageError

type UnexpectedMessageError struct {
	Message *Message
}

UnexpectedMessageError is the message that answered a send expecting an acknowledgement only — matter.js UnexpectedMessageError (protocol/errors.ts:22-28) with its receivedMessage, thrown at MessageExchange.ts:815-817, which InteractionMessenger.ts:1155-1161 inspects. It matches ErrUnexpectedMessage.

func (*UnexpectedMessageError) Error

func (e *UnexpectedMessageError) Error() string

func (*UnexpectedMessageError) Is

func (e *UnexpectedMessageError) Is(target error) bool

Is makes the error match ErrUnexpectedMessage.

Jump to

Keyboard shortcuts

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