Documentation
¶
Overview ¶
Package session is the goroutine host for one RIST Simple-profile flow. It owns the real clock, the UDP sockets, and the timer wheel, and drives the sans-I/O flow core: a single event-loop goroutine is the sole owner of the flow.Flow (which is not safe for concurrent use), reader goroutines forward decoded packets to it over channels, and the loop performs the core's returned effects on the wire.
The loop selects over: inbound media (receiver), inbound RTCP, application input (sender Write), the flow's declarative timer, and a liveness ticker. After every input it drains the flow's effects — encoding and sending media and compound RTCP, (re)arming the timer, and queueing delivered payloads for Read — exactly once. Close stops every goroutine without leaks.
Index ¶
- type AdvParams
- type Config
- type LogCategory
- type LogLevel
- type MainParams
- type Session
- func NewAdvListenerSender(conn *socket.Conn, cfg Config) *Session
- func NewAdvReceiver(conn *socket.Conn, cfg Config) *Session
- func NewAdvReceiverCaller(conn *socket.Conn, remote netip.AddrPort, cfg Config) *Session
- func NewAdvSender(conn *socket.Conn, remote netip.AddrPort, cfg Config) *Session
- func NewBondedReceiver(conns []*socket.Conn, group *bonding.Group, cfg Config) *Session
- func NewBondedSender(conn *socket.Conn, remotes [][2]netip.AddrPort, group *bonding.Group, ...) *Session
- func NewListenerSender(conn *socket.Conn, cfg Config) *Session
- func NewMainListenerSender(conn *socket.Conn, cfg Config) *Session
- func NewMainReceiver(conn *socket.Conn, cfg Config) *Session
- func NewMainReceiverCaller(conn *socket.Conn, remote netip.AddrPort, cfg Config) *Session
- func NewMainSender(conn *socket.Conn, remote netip.AddrPort, cfg Config) *Session
- func NewReceiver(conn *socket.Conn, cfg Config) *Session
- func NewReceiverCaller(conn *socket.Conn, peerRTCP netip.AddrPort, cfg Config) *Session
- func NewSender(conn *socket.Conn, mediaAddr, rtcpAddr netip.AddrPort, cfg Config) *Session
- func (s *Session) Authenticated() bool
- func (s *Session) Close() error
- func (s *Session) Err() error
- func (s *Session) MediaPort() int
- func (s *Session) Read(buf []byte) (int, error)
- func (s *Session) ReadOOB(buf []byte) (int, error)
- func (s *Session) SetReadDeadline(t time.Time)
- func (s *Session) SetWriteDeadline(t time.Time)
- func (s *Session) Stats() flow.Stats
- func (s *Session) Write(p []byte) error
- func (s *Session) WriteOOB(p []byte) error
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AdvParams ¶
type AdvParams struct {
// SendKey encrypts outbound media payloads (AES-CTR, payload-only); nil
// disables encryption.
SendKey *crypto.Key
// RecvKey decrypts inbound media payloads; nil disables decryption. It must
// be non-nil exactly when SendKey is (both derive from the same passphrase).
RecvKey *crypto.Decryptor
// GRESendKey / GRERecvKey encrypt and decrypt the Main-profile GRE control
// substrate (the RTCP SDES handshake) when a secret is configured. They are
// SEPARATE crypto instances from SendKey/RecvKey — GRE framing and adv media
// advance independent IV/sequence state — derived from the same passphrase.
// Both nil means a cleartext GRE substrate.
GRESendKey *crypto.Key
GRERecvKey *crypto.Decryptor
// KeySize256 sets the GRE H bit for the encrypted control substrate (true
// for a 256-bit AES key), mirroring MainParams.
KeySize256 bool
// Compression enables LZ4 payload compression on the media send path.
Compression bool
// VirtSrcPort and VirtDstPort are the reduced-overhead virtual ports encoded
// into the optional Flow ID field on the media send path.
VirtSrcPort uint16
VirtDstPort uint16
}
AdvParams carries the Advanced-profile codec parameters. As with MainParams the public layer builds the PSK keys (so the session constructor stays infallible); nil keys mean cleartext Advanced (no encryption).
type Config ¶
type Config struct {
// Flow is the deterministic core's configuration.
Flow flow.Config
// SSRC is the base (even) flow SSRC the sender stamps; for a receiver it
// is the reporter SSRC used in its RTCP until the media SSRC is learned.
SSRC uint32
// CNAME is the SDES canonical name advertised in compound RTCP.
CNAME string
// Bitmask selects the RFC 4585 bitmask NACK encoding instead of the
// default RIST range NACK.
Bitmask bool
// KeepaliveInterval paces the host liveness check.
KeepaliveInterval clock.Microseconds
// SessionTimeout tears the session down after this much peer silence.
SessionTimeout clock.Microseconds
// Logf, when non-nil, receives diagnostic messages tagged with a severity
// and a category. The host maps LogLevel/LogCategory to the public
// ristgo.LogLevel/LogCategory (the session is decoupled from the public
// package to avoid an import cycle).
Logf func(level LogLevel, category LogCategory, format string, args ...any)
// ErrClosed, ErrTimeout, ErrSessionTimeout, and ErrBufferOverflow are the
// sentinel errors the session returns to the caller. The public layer
// supplies its own identities so callers can match them with errors.Is;
// this keeps the session decoupled from the public package (no import
// cycle).
ErrClosed error
ErrTimeout error
ErrSessionTimeout error
ErrBufferOverflow error
// ErrAuth is returned to the caller when the Main-profile EAP-SRP handshake
// fails (wrong credentials or a refused proof). Supplied by the public layer.
ErrAuth error
// ErrOOBUnsupported is returned by WriteOOB/ReadOOB when the session has no
// out-of-band channel (the Simple profile). Supplied by the public layer.
ErrOOBUnsupported error
// Main, when non-nil, selects the Main profile (VSF TR-06-2): the flow is
// tunnelled over a single GRE port instead of the Simple even/odd RTP/RTCP
// pair. nil means the Simple profile.
Main *MainParams
// Adv, when non-nil, selects the Advanced profile (VSF TR-06-3): a single
// UDP port carrying RTP-based media (PT=127, 1 MHz) and native control
// messages, with no GRE framing. At most one of Main/Adv is non-nil; both
// nil means the Simple profile.
Adv *AdvParams
// Source adaptation (TR-06-4 Part 1, see adapt.go). AdaptLQM makes a
// receiver emit periodic Link Quality Messages. RateController + OnRateAdapt,
// when both set on a sender, feed each inbound LQM to the controller and
// report the new encoder-rate target to the application. All three are off by
// default, leaving non-adaptive sessions unchanged.
AdaptLQM bool
RateController *adapt.Controller
OnRateAdapt func(kbps int)
}
Config carries the per-session parameters the host needs, already translated from the public ristgo.Config (kept separate to avoid an import cycle).
type LogCategory ¶
type LogCategory int
LogCategory tags a session diagnostic by subsystem; the host maps it to the public ristgo.LogCategory.
const ( CatSession LogCategory = iota CatCrypto CatSocket CatRTCP CatFlow CatBonding )
Session log categories.
type LogLevel ¶
type LogLevel int
LogLevel is the severity of a session diagnostic; the host maps it to the public ristgo.LogLevel. Values are ordered least-to-most severe.
type MainParams ¶
type MainParams struct {
// SendKey encrypts outbound datagrams; nil disables encryption.
SendKey *crypto.Key
// RecvKey decrypts inbound datagrams; nil disables decryption. It must be
// non-nil exactly when SendKey is (both derive from the same passphrase).
RecvKey *crypto.Decryptor
// KeySize256 sets the GRE H bit for outbound encrypted datagrams (true for
// a 256-bit AES key). Meaningful only when SendKey is non-nil.
KeySize256 bool
// NPD enables null-packet-deletion suppression on the media encode path.
NPD bool
// VirtSrcPort and VirtDstPort are the reduced-overhead virtual ports.
VirtSrcPort uint16
VirtDstPort uint16
// EAPClient, when non-nil, runs the EAP-SRP authenticatee handshake (a Main
// sender authenticating to the peer); outbound media is held until it
// succeeds. EAPServer, when non-nil, runs the authenticator handshake (a
// Main receiver authenticating the peer); delivery is held until it
// succeeds. At most one is set; both nil means no authentication.
EAPClient *eap.Authenticatee
EAPServer *eap.Authenticator
// UseKeyAsPassphrase enables the EAP-SRP use_key_as_passphrase data-channel
// keying: when SRP is configured WITHOUT a pre-shared Secret, the media PSK
// keys are derived from the SRP session key K (both directions) on a
// successful handshake and installed into the running codec. SendKey/RecvKey
// are nil at construction in this mode (no secret); the handshake fills them.
// Meaningful only when EAPClient or EAPServer is set.
UseKeyAsPassphrase bool
// EAPKeySize256 selects the AES key size derived from K under
// use_key_as_passphrase: true for 256-bit (the libRIST default when no
// aes-type is given, since _librist_crypto_psk_set_passphrase defaults
// key_size to 256), false for 128-bit. Meaningful only when
// UseKeyAsPassphrase is set.
EAPKeySize256 bool
// EAPKeyRotation is the key-rotation threshold for the K-derived send key
// (packets per nonce; 0 = the library default). Meaningful only under
// UseKeyAsPassphrase.
EAPKeyRotation int
}
MainParams carries the Main-profile codec parameters. The public layer builds the PSK keys (so the session constructor stays infallible) and supplies the virtual ports; nil keys mean cleartext Main (no encryption).
type Session ¶
type Session struct {
// contains filtered or unexported fields
}
Session hosts one flow. Construct it with NewSender or NewReceiver.
func NewAdvListenerSender ¶
NewAdvListenerSender builds an Advanced-profile listener-sender that binds the single UDP port and learns the receiver from its inbound traffic. cfg.Adv must be set.
func NewAdvReceiver ¶
NewAdvReceiver builds an Advanced-profile receiver that reads media and control over the single UDP socket conn and learns the sender's address from inbound traffic. cfg.Adv must be set.
func NewAdvReceiverCaller ¶
NewAdvReceiverCaller builds an Advanced-profile caller-receiver that dials remote over the single UDP socket, announcing itself until the listening sender streams. cfg.Adv must be set.
func NewAdvSender ¶
NewAdvSender builds an Advanced-profile sender that transmits RTP-based media and reads control over the single UDP socket conn, addressing remote. cfg.Adv must be set.
func NewBondedReceiver ¶
NewBondedReceiver builds a Simple-profile bonded receiver: one socket per path, all feeding flow into a single deduplicated ring. group must already have a path registered per conn (index = conn index); the constructor registers them if empty.
func NewBondedSender ¶
func NewBondedSender(conn *socket.Conn, remotes [][2]netip.AddrPort, group *bonding.Group, cfg Config) *Session
NewBondedSender builds a Simple-profile bonded sender: one socket that duplicates every media datagram to each remote {media, rtcp} pair. conn is the local ephemeral socket; remotes are the per-path receiver addresses.
func NewListenerSender ¶
NewListenerSender builds a Simple-profile listener-sender: a sender that binds a well-known port and waits for a caller-receiver to announce itself, then streams. The peer is not seeded — peer.RTCP is learned from the receiver's inbound RTCP and peer.Media is inferred as its RTCP port − 1 (the even/odd rule) — so sendMedia holds the stream until a receiver is known.
func NewMainListenerSender ¶
NewMainListenerSender builds a Main-profile listener-sender that binds the single GRE port and learns the receiver from its inbound traffic. cfg.Main must be set.
func NewMainReceiver ¶
NewMainReceiver builds a Main-profile receiver that reads media and feedback over the single GRE socket conn and learns the sender's address from inbound traffic. cfg.Main must be set.
func NewMainReceiverCaller ¶
NewMainReceiverCaller builds a Main-profile caller-receiver that dials remote over the single GRE socket, announcing itself until the listening sender streams. cfg.Main must be set.
func NewMainSender ¶
NewMainSender builds a Main-profile sender that tunnels media and reads feedback over the single GRE socket conn, addressing remote. cfg.Main must be set.
func NewReceiver ¶
NewReceiver builds a receiver-role session that reads RTP and RTCP on conn and learns the sender's return addresses from inbound traffic.
func NewReceiverCaller ¶
NewReceiverCaller builds a Simple-profile caller-receiver: a receiver that dials a listening sender instead of binding a well-known port. It is seeded with the sender's RTCP address (peerRTCP) and announces itself immediately and every keepalive interval; the listening sender learns this receiver from those Receiver Reports and starts streaming. conn is an ephemeral even/odd socket pair so the sender can infer this receiver's media port as its RTCP port − 1.
func NewSender ¶
NewSender builds a sender-role session that transmits RTP to mediaAddr and compound RTCP to rtcpAddr, and reads feedback on conn's RTCP socket.
func (*Session) Authenticated ¶
Authenticated reports whether the data channel is open: true for a Simple session or a Main session without EAP, and for a Main+EAP session once the EAP-SRP handshake has succeeded. It is safe to call concurrently.
func (*Session) Close ¶
Close shuts the session down: it stops the event loop and reader goroutines, closes the sockets, and waits for every goroutine to exit. It is idempotent and safe to call concurrently with Read/Write.
func (*Session) Read ¶
Read returns the next in-order, ARQ-recovered media payload (receiver role). It has stream semantics: a payload larger than buf is returned across successive calls. It blocks until data is available, the read deadline passes (ErrTimeout), or the session closes (ErrClosed, after any buffered payloads are drained).
Read is not safe to call from multiple goroutines concurrently.
func (*Session) ReadOOB ¶
ReadOOB returns the next received out-of-band datagram (Main/Advanced only). Unlike Read it is datagram-oriented: each call returns exactly one OOB payload, truncated to len(buf). It returns ErrOOBUnsupported on the Simple profile, and blocks until an OOB datagram arrives, the read deadline passes (ErrTimeout), or the session closes (ErrClosed, after draining buffered OOB).
func (*Session) SetReadDeadline ¶
SetReadDeadline sets the deadline for Read; a zero time clears it. A pending Read is woken so it observes the new deadline.
func (*Session) SetWriteDeadline ¶
SetWriteDeadline sets the deadline for Write; a zero time clears it. A pending Write is woken so it observes the new deadline.
func (*Session) Write ¶
Write enqueues one application payload for transmission (sender role). It copies p — the flow retains the payload in its retransmit history, so the caller may reuse its buffer once Write returns. It blocks until the payload is accepted by the event loop (back-pressure when the loop is saturated), the write deadline passes (ErrTimeout), or the session closes (ErrClosed).
Write is not safe to call from multiple goroutines concurrently.
func (*Session) WriteOOB ¶
WriteOOB enqueues one out-of-band datagram for transmission (Main/Advanced profiles only). OOB rides the same socket as media but bypasses ARQ entirely — fire-and-forget, like libRIST's rist_oob_write. It returns ErrOOBUnsupported when the session has no OOB channel (the Simple profile). It blocks under back-pressure, honoring the write deadline (ErrTimeout) and close (ErrClosed).