interaction

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: 14 Imported by: 0

Documentation

Overview

Package interaction is the controller's Interaction Model client (ADR 0020, stages 2 and 3), ported from matter.js packages/protocol/src/action/client/ (ClientInteraction.ts, InputChunk.ts, subscription/) and the client half of interaction/InteractionMessenger.ts at 0ceb202d: Invoke (one command), Read with events and filters, Write, Subscribe with the registry of subscriptions and their liveness, the handler of the reports a peer pushes, and sustained subscriptions. An Interaction is bound to an exchange Provider: one session, or a peer whose sessions come and go. Invoke batching and splitting, ICD wakefulness, TCP and large messages are not ported.

The messages are encoded and decoded with im/'s client encoders and decoders, the shapes of matter.js's TLV message definitions.

Index

Constants

View Source
const (
	DefaultTimedRequestTimeout                = 10 * time.Second
	DefaultMinimumResponseTimeoutWithFailsafe = 30 * time.Second
)

Timeouts of the client. Mirrors matter.js packages/protocol/src/action/client/ClientInteraction.ts:159 (DEFAULT_TIMED_REQUEST_TIMEOUT = 10 s) and :160 (DEFAULT_MINIMUM_RESPONSE_TIMEOUT_WITH_FAILSAFE = 30 s) at 0ceb202d.

View Source
const (
	DefaultReadPathsSupported      = 9
	DefaultSubscribePathsSupported = 3
)

Path floors of the base exchange provider: the CapabilityMinima minimums a peer that reports none is assumed to support. Mirrors matter.js packages/protocol/src/protocol/ExchangeProvider.ts:85-90 at 0ceb202d.

View Source
const (
	SubscriptionProcessingTime            = 10 * time.Second
	DefaultMinIntervalFloor               = time.Second
	SubscriptionMaxIntervalPublisherLimit = 60 * time.Minute
)

Subscription defaults. Mirrors matter.js packages/protocol/src/action/client/ClientInteraction.ts:96 (SUBSCRIPTION_PROCESSING_TIME = 10 s), :149 (DEFAULT_MIN_INTERVAL_FLOOR = 1 s) and :157 (SUBSCRIPTION_MAX_INTERVAL_PUBLISHER_LIMIT = 60 min) at 0ceb202d.

View Source
const NoSubscription = ^uint32(0)

NoSubscription is the id of a subscription the peer has not granted yet — ClientSubscription.NO_SUBSCRIPTION (ClientSubscription.ts:34, :104).

Variables

View Source
var (
	// ErrNoSubscriptions is a Subscribe on an interaction without a
	// registry (Config.Subscriptions).
	ErrNoSubscriptions = errors.New("interaction: no subscription registry")
	// ErrUncommissioned is a Subscribe to a peer without a peer address —
	// matter.js "Subscription unavailable because peer is uncommissioned"
	// (ClientInteraction.ts:991-994).
	ErrUncommissioned = errors.New("interaction: subscription unavailable because peer is uncommissioned")
)

Errors of Subscribe.

View Source
var DefaultSustainRetries = RetrySchedule{
	InitialInterval: 15 * time.Second,
	BackoffFactor:   2,
	MaximumInterval: time.Hour,
	JitterFactor:    0.25,
}

DefaultSustainRetries is the schedule a sustained subscription retries on: 15 s, doubling, at most an hour, a quarter of jitter, no timeout. Mirrors matter.js packages/protocol/src/action/client/subscription/SustainedSubscription.ts:483-499 (SustainedSubscription.DefaultRetrySchedule) at 0ceb202d.

View Source
var ErrMalformedRequest = errors.New("interaction: malformed request")

ErrMalformedRequest is a request matter.js refuses to formulate — MalformedRequestError (action/request/MalformedRequestError.ts).

View Source
var ErrNoResponse = errors.New("interaction: no response for the command")

ErrNoResponse is an InvokeResponse without an entry for the command: matter.js #invokeCommand then returns undefined (ControllerCommissioningFlow.ts:510-529).

View Source
var ErrNoSession = errors.New("interaction: no session")

ErrNoSession is a provider without a session to run the exchange on — matter.js's "No existing session available for probe" (PeerExchangeProvider.ts:118-121) and a closed dedicated session.

View Source
var ErrRequestTooLarge = errors.New("interaction: request does not fit one message")

ErrRequestTooLarge is a request that does not fit one message even without its DataVersionFilters — matter.js's MatterFlowError of InteractionMessenger.ts:1010-1014.

View Source
var ErrUnexpectedMessage = errors.New("interaction: unexpected message")

ErrUnexpectedMessage is a reply that is not the message the interaction expects — matter.js UnexpectedDataError / MatterFlowError (InteractionMessenger.ts:186-190, :924-928).

Functions

func Interval

func Interval(d time.Duration) *time.Duration

Interval returns d as a subscription interval bound.

func ListChunked

func ListChunked(cluster, attribute uint32) bool

ListChunked reports whether a list value of the attribute is chunked by default: every attribute but AccessControl ACL and Extension (Write.ts:18-21, isAclOrExtensionPath).

func Raw

func Raw(n spec.Node) spec.Encodable

Raw writes a node tree as a value.

Types

type AttributeData

type AttributeData struct {
	// Path is the attribute's concrete path (node, endpoint, cluster,
	// attribute; no list index).
	Path im.ConcreteAttributePath
	// DataVersion is the cluster's data version, 0 when the report carried
	// none (InputChunk.ts:309-310).
	DataVersion uint32
	// Value is the value as a node tree; a list reassembled from its chunks.
	Value spec.Node
}

AttributeData is one attribute value of a report.

type AttributeStatus

type AttributeStatus struct {
	Path          im.ConcreteAttributePath
	Status        im.StatusCode
	ClusterStatus *uint8
}

AttributeStatus is one attribute status of a report.

type Config

type Config struct {
	// Subscriptions is the controller's subscription registry
	// ([NewSubscriptions]); Subscribe needs it — matter.js takes it from
	// the environment (ClientInteraction.ts:188-190, :252-257).
	Subscriptions *Subscriptions
	// Logger receives the diagnostics; nil discards them.
	Logger *slog.Logger
	// Clock paces the sustained subscriptions' retries; nil is the
	// system clock.
	Clock exchange.Clock
	// Rand returns the retry jitter draw in [0, 1); nil is
	// math/rand/v2.Float64.
	Rand func() float64
}

Config configures an Interaction — what matter.js ClientInteraction takes from its context (ClientInteraction.ts:140-147).

type EventData

type EventData struct {
	Path     im.ConcreteEventPath
	Number   uint64
	Priority im.EventPriority
	// Timestamp is the lossy convenience of InputChunk.ts:388-389: the
	// epoch timestamp, else the system one, else the delta epoch one, else
	// the delta system one, else 0.
	Timestamp uint64
	// The four timestamps as the event carried them, nil when absent.
	EpochTimestamp       *uint64
	SystemTimestamp      *uint64
	DeltaEpochTimestamp  *uint64
	DeltaSystemTimestamp *uint64
	// Value is the event's data, HasValue false when it carried none.
	Value    spec.Node
	HasValue bool
}

EventData is one event of a report — matter.js ReadResult.EventValue as InputChunk.ts:356-413 builds it.

type EventStatus

type EventStatus struct {
	Path          im.ConcreteEventPath
	Status        im.StatusCode
	ClusterStatus *uint8
}

EventStatus is one event status of a report.

type ExchangeOptions

type ExchangeOptions struct {
	// RequireExistingSession uses the newest session and never connects.
	RequireExistingSession bool
	// AddressOverride sends the exchange to this address instead of the
	// session's.
	AddressOverride *net.UDPAddr
	// ConnectionTimeout bounds the connection a peer provider waits for:
	// 0 is the peer set's default, negative waits without bound (matter.js
	// Forever, ClientInteraction.ts:1095).
	ConnectionTimeout time.Duration
}

ExchangeOptions configures Provider.InitiateExchange — the part of matter.js NewExchangeOptions (ExchangeProvider.ts:20-63) the controller uses.

type Interaction

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

Interaction is the client side of the Interaction Model towards one peer — matter.js ClientInteraction (ClientInteraction.ts:165-1259 at 0ceb202d) bound to an exchange Provider: a session (New) or a peer whose sessions come and go (ForPeer). It is safe for concurrent use; each call runs on its own exchange.

func Bind

func Bind(p Provider, cfg Config) *Interaction

Bind returns the interaction over provider p.

func ForPeer

func ForPeer(p *peer.Peer, cfg Config) *Interaction

ForPeer returns the interaction over peer p.

func New

func New(mgr *exchange.Manager, s *exchange.Session, log *slog.Logger) *Interaction

New returns the interaction over session s of mgr — matter.js DedicatedChannelExchangeProvider (ExchangeProvider.ts:122-164). A nil logger discards.

func (*Interaction) Invoke

func (c *Interaction) Invoke(ctx context.Context, path im.ConcreteCommandPath, fields spec.Encodable, opts InvokeOptions) (Result, error)

Invoke invokes one command on a fresh exchange and returns the peer's answer; a status other than Success is a *StatusError. fields is the request payload (a generated request's value), nil for an empty one. Mirrors matter.js ClientInteraction.#invokeSingle (ClientInteraction.ts:434-474) with InteractionClientMessenger .sendInvokeCommand (interaction/InteractionMessenger.ts:1061-1108) at 0ceb202d:

  • a timed invoke first sends a TimedRequest and waits for its Success StatusResponse (:438-440, InteractionMessenger.ts:1124-1136);
  • the single command goes without a commandRef (:457-464);
  • the processing time is ExpectedProcessingTime, else 30 s with the extended failsafe timeout, else the exchange's default (:466-474), for the send's final wait and the wait for the response;
  • a chunked InvokeResponse is acknowledged with a StatusResponse Success after every chunk with more to come and its entries are accumulated (InteractionMessenger.ts:1082-1105);
  • the first entry is the answer, as the flow's #invokeCommand reads it (ControllerCommissioningFlow.ts:506-530): a CommandStatusIB other than Success is a *StatusError.

Errors of the exchange layer pass through unchanged.

func (*Interaction) MaximumPeerResponseTime

func (c *Interaction) MaximumPeerResponseTime(ept time.Duration, includeSending bool) time.Duration

MaximumPeerResponseTime is the longest wait for the peer's answer to a message with expected processing time ept: our retransmissions, ept and the 5 s buffer, plus — with includeSending — the peer's retransmissions back to us. Mirrors matter.js ClientInteraction.maximumPeerResponseTime (ClientInteraction.ts:1249-1251), the provider's computation.

func (*Interaction) Provider

func (c *Interaction) Provider() Provider

Provider is the interaction's exchange provider.

func (*Interaction) Read

func (c *Interaction) Read(ctx context.Context, paths ...im.ConcreteAttributePath) (*Report, error)

Read reads attributes on a fresh exchange — Interaction.ReadWith with attribute paths only.

func (*Interaction) ReadWith

func (c *Interaction) ReadWith(ctx context.Context, r ReadRequest) (*Report, error)

ReadWith reads attributes and events on a fresh exchange and returns the report, its chunks merged. Mirrors matter.js ClientInteraction.read (ClientInteraction.ts:262-298) at 0ceb202d: more paths than the provider's readPathsSupported is only logged (:263-268); the request is encoded to fit one message (InteractionMessenger.ts:994-1050); the reports are read as readDataReports does (:938-972) and each chunk goes through InputChunk (action/client/InputChunk.ts) — a list continued in the next chunk is reassembled, a malformed entry skipped. Errors of the exchange layer pass through unchanged.

func (*Interaction) Session

func (c *Interaction) Session() *exchange.Session

Session is the session the interaction runs on — the provider's dedicated session, or the peer's newest one (nil when none).

func (*Interaction) Subscribe

func (c *Interaction) Subscribe(ctx context.Context, req SubscribeRequest) (*Subscription, error)

Subscribe subscribes on a fresh exchange. Mirrors matter.js ClientInteraction.subscribe (ClientInteraction.ts:978-1123) at 0ceb202d:

  • a request without paths is refused, more paths than the provider's subscribePathsSupported only logged (:981-989);
  • the peer must have a peer address (:991-994);
  • ReplaceSubscriptions closes our subscriptions with the peer first (:996-1008);
  • the intervals default to 1 s and 60 min, the ceiling may not be below the floor (:1010-1021), and each is at most 65535 s (Subscribe.ts:46-60);
  • the attempt (:1023-1078): the request with the intervals in seconds, encoded to fit one message (InteractionMessenger.ts:1052-1055); the priming report's chunks read and acknowledged (:1048, InteractionMessenger.ts:938-972) and handed to Updated; the SubscribeResponse; the subscription registered by (peer, id), its liveness timeout its maximum interval plus twice the maximum peer response time for a 10 s processing time (:1054-1063).

ctx bounds the establishment of a plain subscription. A sustained one (Sustain) is returned at once and establishes itself on its own until closed (:1092-1115).

func (*Interaction) Write

func (c *Interaction) Write(ctx context.Context, writes []WriteRequest, opts WriteOptions) (WriteStatuses, error)

Write writes attributes on a fresh exchange. Mirrors matter.js ClientInteraction.write (ClientInteraction.ts:365-429) with Write() (action/request/Write.ts:43-185) and InteractionClientMessenger.sendWriteCommand (interaction/InteractionMessenger.ts:1110-1162) at 0ceb202d:

  • a DataVersion needs a concrete endpoint, and a write needs at least one attribute (Write.ts:64-69, :105-107);
  • a list value becomes the empty list (REPLACE-ALL) and one append per element with a null ListIndex, unless chunking is off or the path is AccessControl ACL or Extension (:149-171);
  • a timed write first sends a TimedRequest on the same exchange and waits for its Success (:369-371; the timeout defaults to 10 s, :159);
  • one WriteRequest, MoreChunkedMessages false (Write.ts:77); one that does not fit a message, or a timed one whose WriteResponse might not, is an ErrRequestTooLarge before anything is sent;
  • with SuppressResponse the send expects an acknowledgement only; a message in its place is tolerated unless it is a StatusResponse with an error (IM:1138-1162, the "Matter-SDK bug" of :1156), and the result is nil (:382-384);
  • otherwise the WriteResponse's statuses are the result, an empty one an empty result (:385-387).

type InvokeOptions

type InvokeOptions struct {
	// ExpectedProcessingTime is the peer's processing time of the command;
	// 0 is the default (ClientInteraction.ts:466-474).
	ExpectedProcessingTime time.Duration
	// ExtendedFailSafeTimeout is useExtendedFailSafeMessageResponseTimeout:
	// without an ExpectedProcessingTime the command's processing time is
	// [DefaultMinimumResponseTimeoutWithFailsafe] (:466-474).
	ExtendedFailSafeTimeout bool
	// Timed sends a TimedRequest first (:438-440) and marks the invoke as
	// timed.
	Timed bool
	// TimedTimeout is the TimedRequest's timeout; 0 is
	// [DefaultTimedRequestTimeout] (:439).
	TimedTimeout time.Duration
	// SuppressResponse asks the peer for no InvokeResponse: the send
	// expects an acknowledgement only and Invoke returns the zero Result.
	SuppressResponse bool
}

InvokeOptions configures Interaction.Invoke — the options of matter.js Invoke.Definition the commissioning flow sets.

type Provider

type Provider interface {
	// InitiateExchange opens an IM exchange with the peer.
	InitiateExchange(ctx context.Context, opts ExchangeOptions) (*exchange.Exchange, error)
	// PeerAddress is the peer's address, false for an uncommissioned peer
	// (a PASE session).
	PeerAddress() (exchange.PeerAddress, bool)
	// MaximumPeerResponseTime is the longest wait for the peer's answer.
	MaximumPeerResponseTime(ept time.Duration, includeSending bool) time.Duration
	// VerifyReachability verifies the peer answers, driving recovery; the
	// base reports reachable (:114-116).
	VerifyReachability(ctx context.Context) bool
	// ReadPathsSupported and SubscribePathsSupported are the peer's path
	// floors (:85-90).
	ReadPathsSupported() int
	SubscribePathsSupported() int
	// Session is the dedicated session, or the newest one; nil for none.
	Session() *exchange.Session
	// Manager is the exchange manager the sessions live on.
	Manager() *exchange.Manager
}

Provider gives an interaction its exchanges — matter.js ExchangeProvider (ExchangeProvider.ts:71-117).

func PeerProvider

func PeerProvider(p *peer.Peer) Provider

PeerProvider is the provider over peer p — matter.js PeerExchangeProvider (packages/protocol/src/peer/PeerExchangeProvider.ts:19-163): each exchange runs on the peer's newest session, connecting first unless RequireExistingSession is set (:73-150), reachability is the peer's (:69-71).

func SessionProvider

func SessionProvider(mgr *exchange.Manager, s *exchange.Session) Provider

SessionProvider is the provider bound to session s of mgr — matter.js DedicatedChannelExchangeProvider (ExchangeProvider.ts:122-164).

type ReadRequest

type ReadRequest struct {
	// Attributes are the attribute paths, wildcards allowed.
	Attributes []im.ConcreteAttributePath
	// Events are the event paths, wildcards allowed.
	Events []im.ConcreteEventPath
	// EventFilters are the minimum event numbers; matter.js sets eventMin
	// only (Read.ts:171-176).
	EventFilters []im.EventMinimumNumber
	// DataVersionFilters skip clusters whose data the client holds; dropped
	// or trimmed when the request would not fit one message
	// (InteractionMessenger.ts:998-1050).
	DataVersionFilters []im.DataVersionFilter
	// NoFabricFilter reads fabric-scoped lists unfiltered; a read is
	// fabric-filtered by default (fabricFilter = true, Read.ts:40).
	NoFabricFilter bool
}

ReadRequest is a read — matter.js Read() (action/request/Read.ts:28-91) with numeric paths.

type Report

type Report struct {
	// SubscriptionID is the report's subscription id, 0 for a read's
	// report: the first chunk's — matter.js hands each chunk's DataReport,
	// subscriptionId included, to InputChunk (action/client/InputChunk.ts:166-169)
	// and the handler reads the id off the initial report
	// (ClientSubscriptionHandler.ts:77) at 0ceb202d.
	SubscriptionID uint32
	// Session is the session the report arrived over — the exchange's
	// session matter.js takes the peer from and hands to reportStarted
	// (ClientSubscriptionHandler.ts:89, :108-112).
	Session       *exchange.Session
	Attributes    []AttributeData
	Statuses      []AttributeStatus
	Events        []EventData
	EventStatuses []EventStatus
}

Report is the data of a read or of one subscription report, its chunks merged.

func (*Report) Empty

func (r *Report) Empty() bool

Empty reports whether the report carries no attribute or event entry.

func (*Report) Value

func (r *Report) Value(endpoint uint16, cluster, attribute uint32) (spec.Node, bool)

Value returns the value the report carries for the attribute.

type Result

type Result struct {
	// Command is the response command id; HasFields reports whether the
	// answer carried a response command, Fields its fields.
	Command   uint32
	HasFields bool
	Fields    spec.Node
	// Status is the command's status: Success with fields, or the
	// CommandStatusIB's.
	Status im.StatusCode
	// ClusterStatus is the cluster-specific status, nil when absent.
	ClusterStatus *uint8
}

Result is the peer's answer to the command — the "cmd-response" or "cmd-status" entry of matter.js's decoded invoke result.

type RetrySchedule

type RetrySchedule struct {
	InitialInterval time.Duration
	BackoffFactor   float64
	MaximumInterval time.Duration
	JitterFactor    float64
}

RetrySchedule configures the retries of a sustained subscription — matter.js RetrySchedule.Configuration (packages/general/src/net/RetrySchedule.ts:67-109). A zero field takes the schedule's default (an initial interval of 1 s, a backoff of 2); a zero MaximumInterval and JitterFactor mean none.

type StatusError

type StatusError struct {
	Status im.StatusCode
	// ClusterStatus is the cluster-specific status, nil when absent.
	ClusterStatus *uint8
	// Path is the attribute the status is for — a write's failing path
	// (matter.js PathError, action/response/WriteResult.ts:41-59) — nil for
	// an interaction-level status.
	Path *im.ConcreteAttributePath
}

StatusError is an interaction the peer ended with a status other than Success — a CommandStatusIB of the command (matter.js StatusResponseError.create, ControllerCommissioningFlow.ts:519-523) or a StatusResponse in place of the expected message (ReceivedStatusResponseError, InteractionMessenger.ts:201-214, :920-923).

func (*StatusError) Error

func (e *StatusError) Error() string

type SubscribeRequest

type SubscribeRequest struct {
	// Attributes, Events, EventFilters, DataVersionFilters and
	// NoFabricFilter are a read's ([ReadRequest]).
	Attributes         []im.ConcreteAttributePath
	Events             []im.ConcreteEventPath
	EventFilters       []im.EventMinimumNumber
	DataVersionFilters []im.DataVersionFilter
	NoFabricFilter     bool
	// ReplaceSubscriptions is keepSubscriptions false: our other
	// subscriptions with the peer are closed first and the peer is told to
	// drop its own (CI:996-1008). keepSubscriptions defaults to true
	// (Subscribe.ts:44).
	ReplaceSubscriptions bool
	// MinIntervalFloor is the floor of the reporting interval; nil is
	// [DefaultMinIntervalFloor] (CI:1011).
	MinIntervalFloor *time.Duration
	// MaxIntervalCeiling is the ceiling; nil is
	// [SubscriptionMaxIntervalPublisherLimit] (CI:1012).
	MaxIntervalCeiling *time.Duration
	// Updated receives each report with data, its chunks merged — the
	// priming report too.
	Updated func(r *Report)
	// KeepaliveReceived is called for an empty report (Subscribe.ts:33-37).
	KeepaliveReceived func()
	// Closed is called when the subscription closed (Subscribe.ts:28-31).
	Closed func()
	// Sustain keeps the subscription alive: when the underlying
	// subscription is lost it is re-established, the peer's reachability
	// verified first (ClientSubscribe.ts:14-19, SustainedSubscription.ts).
	Sustain bool
	// BootstrapRead, for a sustained subscription, runs before an attempt
	// until it succeeds — the hook of bootstrapWithRead
	// (SustainedSubscription.ts:187-204), which the node layer fills; an
	// error fails the attempt.
	BootstrapRead func(ctx context.Context) error
	// ActiveChanged, for a sustained subscription, is called when it gains
	// or loses its underlying subscription (SustainedSubscription.ts:83-95).
	ActiveChanged func(active bool)
	// RefreshRequest, for a sustained subscription, rewrites the request
	// before every attempt but the very first and again right after a
	// successful bootstrap read — matter.js refreshRequest
	// (subscription/ClientSubscribe.ts:30-34; SustainedSubscription.ts:182-186,
	// :200-203), which the node layer fills to send its current
	// DataVersionFilters and event minimum. It rewrites the paths and
	// filters; the interval bounds stay Subscribe's and the subscription
	// keeps its callbacks.
	RefreshRequest func(SubscribeRequest) SubscribeRequest
	// MaxEventNumberChanged, for a sustained subscription, is called with
	// the new highest event number once a report raised it, after Updated
	// returned and before the report counts as delivered; an error is
	// logged and the subscription continues. matter.js
	// maxEventNumberChanged (SustainedSubscription.ts:354-364).
	MaxEventNumberChanged func(number uint64) error
}

SubscribeRequest is a subscription — matter.js Subscribe (action/request/Subscribe.ts:18-63) with ClientSubscribe (subscription/ClientSubscribe.ts), numeric paths.

type Subscription

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

Subscription is a subscription with a peer. A plain one is the Matter subscription the peer granted — matter.js PeerSubscription (PeerSubscription.ts:15-54) over ClientSubscription (ClientSubscription.ts:19-101); a sustained one keeps re-establishing its underlying subscription (SubscribeRequest.Sustain).

func (*Subscription) Active

func (s *Subscription) Active() bool

Active reports whether a sustained subscription holds an established underlying subscription — SustainedSubscription.active (SustainedSubscription.ts:83-95); a plain subscription is active until closed.

func (*Subscription) Close

func (s *Subscription) Close()

Close closes the subscription: its work is aborted, it leaves the registry and the request's Closed callback runs — after a sustained subscription's loop ended. The peer is told nothing (ClientRequest.ts:60-61): it learns from the InvalidSubscription its next report gets. Mirrors ClientSubscription.close (ClientSubscription.ts:60-92). It is idempotent.

func (*Subscription) Done

func (s *Subscription) Done() <-chan struct{}

Done is closed once the subscription closed and its Closed callback ran.

func (*Subscription) ID

func (s *Subscription) ID() uint32

ID is the subscription id; NoSubscription for a sustained subscription between underlying ones.

func (*Subscription) MaxEventNumber added in v0.7.3

func (s *Subscription) MaxEventNumber() (uint64, bool)

MaxEventNumber is the highest event number of the reports a sustained subscription delivered to its Updated callback, false before the first event; it never decreases. A plain subscription reports none. Mirrors matter.js SustainedSubscription.maxEventNumber (packages/protocol/src/action/client/subscription/SustainedSubscription.ts:105-114) at 862ad75f.

func (*Subscription) MaxInterval

func (s *Subscription) MaxInterval() time.Duration

MaxInterval is the maximum interval the peer granted; for a sustained subscription the underlying one's, one hour without one (SustainedSubscription.ts:426-428).

func (*Subscription) Peer

func (s *Subscription) Peer() exchange.PeerAddress

Peer is the peer's address.

type Subscriptions

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

Subscriptions is the controller's subscription registry: the user-facing subscriptions, the peer subscriptions by (peer, subscription id) the inbound reports are routed by, and the liveness timer. One serves a controller (one exchange manager). It is matter.js ClientSubscriptions (packages/protocol/src/action/client/subscription/ClientSubscriptions.ts:34-278 at 0ceb202d). It is safe for concurrent use.

func NewSubscriptions

func NewSubscriptions(cfg SubscriptionsConfig) *Subscriptions

NewSubscriptions returns an empty registry.

func (*Subscriptions) Active

func (r *Subscriptions) Active() []*Subscription

Active returns the user-facing subscriptions (the iterator of :186-191).

func (*Subscriptions) AddPeer

func (r *Subscriptions) AddPeer(s *Subscription)

AddPeer registers a peer subscription by (peer, id) and restarts the liveness timer (:132-143).

func (*Subscriptions) BlockNewActivity

func (r *Subscriptions) BlockNewActivity(ctx context.Context) error

BlockNewActivity blocks new report processing, ends the reads in flight and waits for them — ClientSubscriptions.blockNewActivity (:73-95). A second call waits as well. It returns ctx's error when ctx ends first.

func (*Subscriptions) Close

func (r *Subscriptions) Close(ctx context.Context) error

Close terminates every subscription: new reads are blocked and the reads in flight drained, the timer stopped, every user-facing subscription closed and waited for — ClientSubscriptions.close (:193-219). It returns ctx's error when ctx ends first.

func (*Subscriptions) CloseForPeer

func (r *Subscriptions) CloseForPeer(addr exchange.PeerAddress)

CloseForPeer closes the peer subscriptions of addr, so they are re-established — after a session migrated to a new address (PeerAddressMonitor.ts:244-246), as ClientSubscriptions.closeForPeer does (:160-171).

func (*Subscriptions) Delete

func (r *Subscriptions) Delete(s *Subscription)

Delete unregisters a subscription (:173-184).

func (*Subscriptions) GetPeer

func (r *Subscriptions) GetPeer(addr exchange.PeerAddress, id uint32) *Subscription

GetPeer returns the peer subscription with id, nil for none (:145-150).

func (*Subscriptions) HandleExchange

func (r *Subscriptions) HandleExchange(x *exchange.Exchange, first *exchange.Message)

HandleExchange handles an IM exchange a peer opened with first. Mirrors matter.js ClientSubscriptionHandler (ClientSubscriptionHandler.ts:33-145) at 0ceb202d:

  • a first message other than a ReportData is not a client operation: the controller serves no Interaction Model server, so it is answered InvalidAction as InteractionServerMessenger answers an unsupported message (InteractionMessenger.ts:357-361);
  • while the registry is blocked a report is answered InvalidSubscription (:33-43);
  • a report without a subscription id is answered InvalidSubscription (:76-86), one for an unknown (peer, id) logged and answered InvalidSubscription (:88-104);
  • otherwise the subscription is reading and ReportStarted runs (:108-112); an empty report is a keepalive — KeepaliveReceived, then the report's acknowledgement, further chunks read over (:114-128); a report with data is assembled and handed to Updated, a later chunk naming no or another subscription answered InvalidSubscription and ending it (:129-138, processReports :163-196);
  • in every case the liveness deadline restarts (:139-144).

The chunks are acknowledged as readDataReports does (InteractionMessenger.ts:938-972).

func (*Subscriptions) IsBlocked

func (r *Subscriptions) IsBlocked() bool

IsBlocked reports whether new report processing is blocked (:58-63).

func (*Subscriptions) Register

func (r *Subscriptions) Register(mgr *exchange.Manager)

Register installs the registry's handler of the reports peers push on mgr: the first message of every IM exchange a peer opens on a secure session reaches Subscriptions.HandleExchange — matter.js ClientSubscriptionHandler (requiresSecureSession, ClientSubscriptionHandler.ts:23-31) as Peers.#configureInteractionServer installs it into the node's InteractionServer (packages/node/src/node/client/Peers.ts:546-563, packages/node/src/node/server/InteractionServer.ts:218-228).

func (*Subscriptions) ResetTimer

func (r *Subscriptions) ResetTimer()

ResetTimer restarts the liveness timer for the peer subscriptions — ClientSubscriptions.resetTimer (:221-277): a subscription that is reading is skipped; one without a deadline gets now + its timeout; one past its deadline times out and closes; the timer is armed for the earliest deadline, or stopped when there is none or the registry is blocked.

type SubscriptionsConfig

type SubscriptionsConfig struct {
	// Clock paces the liveness timer; nil is the system clock.
	Clock exchange.Clock
	// Logger receives the diagnostics; nil discards them.
	Logger *slog.Logger
	// ReportStarted is called when a report the peer pushes starts
	// arriving on one of its subscriptions, with the session it arrived
	// over; a priming report does not call it, and a panic in it is
	// logged and contained — matter.js ClientSubscriptions.reportStarted
	// (ClientSubscriptions.ts:152-158).
	ReportStarted func(s *exchange.Session)
}

SubscriptionsConfig configures NewSubscriptions.

type WriteOptions

type WriteOptions struct {
	// Timed sends a TimedRequest first (ClientInteraction.ts:369-371).
	Timed bool
	// TimedTimeout is the TimedRequest's timeout; 0 is
	// [DefaultTimedRequestTimeout]. A timeout marks the write timed
	// (Write.ts:74).
	TimedTimeout time.Duration
	// SuppressResponse asks the peer for no WriteResponse.
	SuppressResponse bool
	// DisableListChunking writes a list value as one AttributeDataIB; by
	// default a list is written as REPLACE-ALL with the empty list and one
	// append per element (chunkLists = true, Write.ts:59, :149-171).
	DisableListChunking bool
}

WriteOptions configures Interaction.Write — matter.js Write.Options (Write.ts:188-199).

type WriteRequest

type WriteRequest struct {
	// Path names the attribute: the endpoint may be a wildcard, the cluster
	// and attribute must be set.
	Path im.ConcreteAttributePath
	// Value is the value to write: a generated type's value, or a node tree
	// through [Raw].
	Value spec.Encodable
	// DataVersion, when set, makes the write conditional; it needs a
	// concrete endpoint (Write.ts:64-69, :128-131).
	DataVersion *uint32
}

WriteRequest is one attribute to write — a Write.Attribute of matter.js (Write.ts:204-218) with numeric ids.

type WriteStatus

type WriteStatus struct {
	Path          im.ConcreteAttributePath
	Status        im.StatusCode
	ClusterStatus *uint8
}

WriteStatus is the peer's status for one written path — matter.js WriteResult.AttributeStatus (action/response/WriteResult.ts:34-39), the path with its ListIndex.

type WriteStatuses

type WriteStatuses []WriteStatus

WriteStatuses is a write's result.

func (WriteStatuses) Err

func (w WriteStatuses) Err() error

Err is nil when every path succeeded, the failing path's *StatusError when one failed, and the failing paths' errors joined when several did. Mirrors matter.js WriteResult.assertSuccess (WriteResult.ts:41-59).

Jump to

Keyboard shortcuts

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