protocol

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Apr 24, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package protocol implements the Matter message framing, session management, exchange tracking, and encrypted message codec.

Index

Constants

View Source
const (
	// FlagSourceNodeID indicates the Source Node ID field is present (bit 2).
	FlagSourceNodeID byte = 1 << 2
	// FlagDSIZMask is the mask for the Destination ID Size bits (bits 0-1).
	FlagDSIZMask byte = 0x03
	// FlagVersionMask is the mask for the message version bits (bits 4-7).
	FlagVersionMask byte = 0xF0
)

Message flag bits (byte 0 of the message header).

View Source
const (
	DSIZNone   byte = 0x00 // No destination node ID present
	DSIZNodeID byte = 0x01 // 64-bit destination node ID
	DSIZGroup  byte = 0x02 // 16-bit group ID
)

DSIZ values for destination node ID encoding.

View Source
const (
	// SecFlagSessionTypeMask is the mask for session type bits (bits 0-1).
	SecFlagSessionTypeMask byte = 0x03
	// SecFlagMX indicates a message extension is present (bit 3).
	SecFlagMX byte = 1 << 3
	// SecFlagC indicates the message is encrypted with a privacy key (bit 5).
	SecFlagC byte = 1 << 5
	// SecFlagP indicates the message header is privacy-encrypted (bit 7).
	SecFlagP byte = 1 << 7
)

Security flag bits (byte 3 of the message header).

View Source
const (
	SessionTypeUnicast byte = 0x00
	SessionTypeGroup   byte = 0x01
)

Session type values.

View Source
const (
	// ExFlagInitiator indicates the sender is the exchange initiator (bit 0).
	ExFlagInitiator byte = 1 << 0
	// ExFlagACK indicates an acknowledgment counter is present (bit 1).
	ExFlagACK byte = 1 << 1
	// ExFlagReliable indicates the message requires reliable delivery (bit 2).
	ExFlagReliable byte = 1 << 2
	// ExFlagSecuredExt indicates a secured extension is present (bit 3).
	ExFlagSecuredExt byte = 1 << 3
	// ExFlagVendor indicates a vendor ID is present in the protocol header (bit 4).
	ExFlagVendor byte = 1 << 4
)

Protocol header exchange flag bits.

Variables

View Source
var ErrExchangeClosed = errors.New("exchange closed")

ErrExchangeClosed is returned by Exchange.Receive when the exchange has been closed (e.g. because the underlying transport connection was lost). Callers can use errors.Is(err, ErrExchangeClosed) to distinguish a connection-loss closure from other receive failures.

Functions

func EncodeMessageHeader

func EncodeMessageHeader(h *MessageHeader) ([]byte, error)

EncodeMessageHeader serializes a MessageHeader into binary form.

func EncodeProtocolHeader

func EncodeProtocolHeader(p *ProtocolHeader) ([]byte, error)

EncodeProtocolHeader serializes a ProtocolHeader into binary form.

Types

type Codec

type Codec struct{}

Codec handles encoding and decoding of complete Matter messages, including encryption and decryption of the payload using AES-CCM.

func NewCodec

func NewCodec() *Codec

NewCodec creates a new Codec.

func (*Codec) Decode

func (c *Codec) Decode(data []byte, session *Session) (*Message, error)

Decode parses a complete wire-format Matter message. For secured sessions, the session's decryption key is used to decrypt the payload.

func (*Codec) Encode

func (c *Codec) Encode(msg *Message, session *Session) ([]byte, error)

Encode serializes a Message into a complete wire-format byte sequence. For secured sessions (non-zero session ID), the payload is encrypted with AES-128-CCM using the session's encryption key.

type Exchange

type Exchange struct {
	// ID is the exchange identifier.
	ID uint16
	// Session is the session this exchange belongs to.
	Session *Session
	// IsInitiator indicates whether the local node initiated this exchange.
	IsInitiator bool

	// SendFunc is the function used to send messages over the transport.
	// If nil, Send is a no-op (for backward compatibility with tests).
	SendFunc func(ctx context.Context, msg *Message) error
	// contains filtered or unexported fields
}

Exchange represents a single Matter exchange — a sequence of messages between two nodes within a session.

func (*Exchange) Close

func (e *Exchange) Close()

Close closes the exchange and its incoming message channel.

func (*Exchange) Receive

func (e *Exchange) Receive(ctx context.Context) (*Message, error)

Receive waits for the next message in this exchange, or returns an error if the context is cancelled or the exchange is closed.

func (*Exchange) Send

func (e *Exchange) Send(ctx context.Context, msg *Message) error

Send stamps the exchange ID and initiator flag on the message, then transmits it via the configured SendFunc. If SendFunc is nil, Send is a no-op (returning nil) for backward compatibility with tests that don't wire up a transport.

type ExchangeManager

type ExchangeManager struct {

	// DefaultSendFunc is assigned to every new exchange created by NewExchange.
	// It provides the transport-level send capability.
	DefaultSendFunc func(ctx context.Context, msg *Message) error

	// OnUnhandled is called when a message arrives for an unknown exchange
	// and the sender is the initiator (i.e., this is a new incoming exchange).
	// If nil, such messages are silently dropped.
	OnUnhandled func(ctx context.Context, exchange *Exchange, msg *Message) error
	// contains filtered or unexported fields
}

ExchangeManager tracks active exchanges and routes incoming messages to the correct exchange. It is safe for concurrent use.

func NewExchangeManager

func NewExchangeManager() *ExchangeManager

NewExchangeManager creates a new ExchangeManager.

func (*ExchangeManager) CloseAll

func (em *ExchangeManager) CloseAll()

CloseAll closes every active exchange and removes it from the manager. This is called when the underlying transport connection is lost so that any goroutine blocked in Exchange.Receive unblocks immediately instead of waiting for a context timeout.

func (*ExchangeManager) CloseExchange

func (em *ExchangeManager) CloseExchange(e *Exchange)

CloseExchange removes an exchange from the manager and closes it.

func (*ExchangeManager) Count

func (em *ExchangeManager) Count() int

Count returns the number of active exchanges.

func (*ExchangeManager) HandleMessage

func (em *ExchangeManager) HandleMessage(ctx context.Context, msg *Message) error

HandleMessage routes an incoming decoded message to the appropriate exchange. If no matching exchange exists and the message is from an initiator, a new exchange is created and the OnUnhandled callback is invoked.

func (*ExchangeManager) NewExchange

func (em *ExchangeManager) NewExchange(ctx context.Context, session *Session) (*Exchange, error)

NewExchange creates a new locally-initiated exchange on the given session.

type Message

type Message struct {
	// Header is the unencrypted message header.
	Header MessageHeader
	// Protocol is the protocol header from within the decrypted payload.
	Protocol ProtocolHeader
	// Payload is the application payload (after the protocol header).
	Payload []byte
}

Message represents a fully decoded Matter message with both headers and payload.

type MessageHeader

type MessageHeader struct {
	// Flags is the message flags byte.
	Flags byte
	// SessionID is the session identifier.
	SessionID uint16
	// SecurityFlags is the security flags byte.
	SecurityFlags byte
	// MessageCounter is the monotonically increasing message counter.
	MessageCounter uint32
	// SourceNodeID is the optional source node ID (present if FlagSourceNodeID is set).
	SourceNodeID uint64
	// HasSourceNodeID indicates whether SourceNodeID is present.
	HasSourceNodeID bool
	// DestinationNodeID is the optional 64-bit destination node ID.
	DestinationNodeID uint64
	// HasDestinationNodeID indicates whether DestinationNodeID is present.
	HasDestinationNodeID bool
	// DestinationGroupID is the optional 16-bit destination group ID.
	DestinationGroupID uint16
	// HasDestinationGroupID indicates whether DestinationGroupID is present.
	HasDestinationGroupID bool
}

MessageHeader represents the unencrypted portion of a Matter message.

func DecodeMessageHeader

func DecodeMessageHeader(data []byte) (*MessageHeader, int, error)

DecodeMessageHeader deserializes a MessageHeader from binary data. It returns the header and the number of bytes consumed.

func (*MessageHeader) SessionType

func (h *MessageHeader) SessionType() byte

SessionType returns the session type from the security flags.

func (*MessageHeader) Version

func (h *MessageHeader) Version() byte

Version returns the message version from the flags byte.

type ProtocolHeader

type ProtocolHeader struct {
	// ExchangeFlags contains the exchange-level flags.
	ExchangeFlags byte
	// ProtocolOpcode is the protocol-specific opcode.
	ProtocolOpcode byte
	// ExchangeID is the exchange identifier.
	ExchangeID uint16
	// ProtocolID identifies the protocol (e.g., 0x0000 for Secure Channel).
	ProtocolID uint16
	// VendorID is the optional vendor ID (present if ExFlagVendor is set).
	VendorID uint16
	// HasVendorID indicates whether VendorID is present.
	HasVendorID bool
	// AckMessageCounter is the optional acknowledgment counter (present if ExFlagACK is set).
	AckMessageCounter uint32
	// HasAckCounter indicates whether AckMessageCounter is present.
	HasAckCounter bool
}

ProtocolHeader represents the protocol header within the decrypted payload.

func DecodeProtocolHeader

func DecodeProtocolHeader(data []byte) (*ProtocolHeader, int, error)

DecodeProtocolHeader deserializes a ProtocolHeader from binary data. It returns the header and the number of bytes consumed.

func (*ProtocolHeader) IsInitiator

func (p *ProtocolHeader) IsInitiator() bool

IsInitiator returns true if the sender is the exchange initiator.

func (*ProtocolHeader) NeedsACK

func (p *ProtocolHeader) NeedsACK() bool

NeedsACK returns true if the message requires reliable delivery acknowledgment.

type Session

type Session struct {
	// ID is the local session identifier.
	ID uint16
	// PeerSessionID is the peer's session identifier.
	PeerSessionID uint16
	// Type is the session type (Unsecured, PASE, CASE).
	Type SessionType
	// LocalNodeID is the local (our) operational node ID for this session.
	// Used in nonce construction when sending messages.
	LocalNodeID uint64
	// PeerNodeID is the peer's node ID.
	// Used in nonce construction when receiving messages (if source node ID not in header).
	PeerNodeID uint64
	// EncryptKey is the session encryption key (16 bytes for AES-128-CCM).
	EncryptKey []byte
	// DecryptKey is the session decryption key (16 bytes for AES-128-CCM).
	DecryptKey []byte
	// AttestationChallenge is the attestation challenge for this session.
	AttestationChallenge []byte
	// contains filtered or unexported fields
}

Session represents a Matter communication session with its security context.

func (*Session) NextMessageCounter

func (s *Session) NextMessageCounter() uint32

NextMessageCounter returns the next outgoing message counter and increments it.

func (*Session) ValidatePeerCounter

func (s *Session) ValidatePeerCounter(counter uint32) error

ValidatePeerCounter checks whether a received message counter is valid (not a replay). It updates the tracking state if valid. Thread-safe.

type SessionTable

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

SessionTable manages active Matter sessions. It is safe for concurrent use.

func NewSessionTable

func NewSessionTable() *SessionTable

NewSessionTable creates a new SessionTable. Session IDs start from 1 (ID 0 is reserved for unsecured sessions).

func (*SessionTable) Count

func (st *SessionTable) Count() int

Count returns the number of active sessions (including the unsecured session if present).

func (*SessionTable) CreateSession

func (st *SessionTable) CreateSession(sessionType SessionType) (*Session, error)

CreateSession allocates a new session with the given type and returns it.

func (*SessionTable) GetSession

func (st *SessionTable) GetSession(id uint16) *Session

GetSession looks up a session by its local ID. Returns nil if not found.

func (*SessionTable) RemoveSession

func (st *SessionTable) RemoveSession(id uint16)

RemoveSession removes a session by its local ID.

func (*SessionTable) UnsecuredSession

func (st *SessionTable) UnsecuredSession() *Session

UnsecuredSession returns the shared unsecured session (ID 0). The message counter is initialized to a random value as required by the Matter spec.

type SessionType

type SessionType int

SessionType distinguishes between the different Matter session types.

const (
	// SessionUnsecured represents an unauthenticated session (session ID 0).
	SessionUnsecured SessionType = iota
	// SessionPASE represents a session established via PASE (Passcode-Authenticated Session Establishment).
	SessionPASE
	// SessionCASE represents a session established via CASE (Certificate-Authenticated Session Establishment).
	SessionCASE
)

func (SessionType) String

func (st SessionType) String() string

String returns a human-readable name for the session type.

Jump to

Keyboard shortcuts

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