socket

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jun 14, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package socket is the UDP transport for RIST. The Simple profile (VSF TR-06-1) uses a pair of unconnected UDP sockets on adjacent even/odd ports — RTP media on the even port P, compound RTCP on the odd port P+1. The Main profile (TR-06-2) tunnels everything over a single GRE port; ListenSingle / ListenEphemeralSingle bind that one socket (the Conn's media and rtcp aliases then refer to it, and the session reads/writes it via ReadMedia/WriteMedia).

The sockets are deliberately unconnected (net.ListenUDP, not DialUDP) and every send takes an explicit destination, so one transport serves both roles: a receiver binds the well-known port pair and learns the sender's source addresses from inbound datagrams, while a sender binds an ephemeral pair and addresses the receiver's well-known ports. Address learning and the even/odd split mirror libRIST (bind, address matching).

This package only moves bytes; it never parses RTP/RTCP or touches the flow core. Read/Write are safe for concurrent use across the two sockets (each *net.UDPConn is independently goroutine-safe), which is how the host runs a reader goroutine per socket alongside the event loop.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Conn

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

Conn is a RIST UDP transport. For the Simple profile it holds a media socket (even port) and an RTCP socket (odd port). For the Main profile it holds one socket carrying everything: media and rtcp both alias it and single is true.

func FromConns

func FromConns(media, rtcp *net.UDPConn) *Conn

FromConns wraps two already-bound UDP sockets (media even, rtcp odd). It lets a caller inject sockets — for tests or to satisfy a PacketConn-style API — and takes ownership: Close closes both.

func Listen

func Listen(host string, port int) (*Conn, error)

Listen binds the media socket to host:port and the RTCP socket to host:port+1. port must be even (TR-06-1 §4: the media port is even, RTCP is the adjacent odd port); port 0 is rejected because the pair cannot be derived from an ephemeral media bind. host may be empty to bind all interfaces. It is the receiver-side constructor.

func ListenEphemeral

func ListenEphemeral(host string) (*Conn, error)

ListenEphemeral binds both sockets to OS-chosen ports on host (empty host binds all interfaces). It is the sender-side constructor: the sender's local ports are arbitrary; the receiver learns them from inbound datagrams.

func ListenEphemeralEvenOdd

func ListenEphemeralEvenOdd(host string) (*Conn, error)

ListenEphemeralEvenOdd binds an OS-chosen even media port and the adjacent odd RTCP port on host (empty host binds all interfaces). It is the Simple-profile caller-receiver constructor: a receiver that dials a listening sender still needs a local even/odd pair, because a Simple listener-sender infers the receiver's media address as its RTCP source port − 1 (the even/odd rule). A probe bind picks a free port; if it is odd the even neighbour below is tried, then port+1. The small TOCTOU window between probe and the real binds is tolerated by retrying.

func ListenEphemeralFamily

func ListenEphemeralFamily(network, host string) (*Conn, error)

ListenEphemeralFamily is ListenEphemeral with an explicit address family ("udp4" or "udp6"). A multicast sender must bind its egress socket in the group's family: a dual-stack ("udp", [::]) socket cannot have an IPv4 multicast interface/TTL set on it (the ipv4 socket options reject a v6-bound fd with EINVAL). network "udp" (the default) preserves the dual-stack unicast behavior.

func ListenEphemeralSingle

func ListenEphemeralSingle(host string) (*Conn, error)

ListenEphemeralSingle binds one OS-chosen UDP socket on host (empty host binds all interfaces) for the Main profile. It is the Main sender-side constructor; the receiver learns the local port from inbound datagrams.

func ListenEphemeralSingleFamily

func ListenEphemeralSingleFamily(network, host string) (*Conn, error)

ListenEphemeralSingleFamily is ListenEphemeralSingle with an explicit address family ("udp4"/"udp6"); see ListenEphemeralFamily for why a multicast sender needs it.

func ListenSingle

func ListenSingle(host string, port int) (*Conn, error)

ListenSingle binds one UDP socket on host:port for the Main profile, where a single GRE-tunnelled port carries both media and feedback (TR-06-2). Unlike Listen it accepts any port (the Main port is not constrained to be even); host may be empty to bind all interfaces. It is the Main receiver-side constructor. Reads and writes use ReadMedia/WriteMedia on the single socket.

func (*Conn) Close

func (c *Conn) Close() error

Close closes both sockets, unblocking any in-flight reads (which return a net.ErrClosed-wrapped error). It is safe to call more than once.

func (*Conn) DTLSEnabled

func (c *Conn) DTLSEnabled() bool

DTLSEnabled reports whether a DTLS session is configured (and so Handshake must run before media flows).

func (*Conn) EnableDTLSClient

func (c *Conn) EnableDTLSClient(remote *net.UDPAddr, cfg *dtls.Config)

EnableDTLSClient configures the Conn to run a DTLS client handshake to remote on Handshake. The RIST sender is the DTLS client.

func (*Conn) EnableDTLSServer

func (c *Conn) EnableDTLSServer(cfg *dtls.Config)

EnableDTLSServer configures the Conn to run a DTLS server handshake, learning the peer from the first inbound datagram on Handshake. The RIST receiver is the DTLS server.

func (*Conn) Handshake

func (c *Conn) Handshake() error

Handshake performs the configured DTLS handshake over the single socket, binding the session to one peer. It is a no-op when DTLS is not enabled. After it returns, ReadMedia/WriteMedia carry application records.

func (*Conn) JoinMulticast

func (c *Conn) JoinMulticast(opts MulticastOptions) error

JoinMulticast joins opts.Group on the receiver's sockets so inbound group traffic is delivered. It joins on both the media and RTCP sockets (the Simple profile even/odd pair); for a single-socket Main/Advanced Conn the two alias one socket, so the second join is skipped. ASM uses JoinGroup; SSM (opts.Source set) uses JoinSourceSpecificGroup, restricting delivery to that source. It is a no-op when opts.Group is not a multicast address.

func (*Conn) MediaPort

func (c *Conn) MediaPort() int

MediaPort returns the local media (even) port the transport is bound to.

func (*Conn) ReadMedia

func (c *Conn) ReadMedia(buf []byte) (int, netip.AddrPort, error)

ReadMedia reads one media (RTP) datagram into buf, returning the byte count and the source address (the sender's media address, for a receiver). When DTLS is enabled (Main profile), it returns the next decrypted application record and the established peer's address.

It uses (*net.UDPConn).ReadFromUDPAddrPort so the per-datagram receive path is allocation-free: a netip.AddrPort is a value type, so the source address is not heap-allocated the way ReadFromUDP's *net.UDPAddr was.

func (*Conn) ReadRTCP

func (c *Conn) ReadRTCP(buf []byte) (int, netip.AddrPort, error)

ReadRTCP reads one RTCP datagram into buf, returning the byte count and the source address. Like ReadMedia it reads via ReadFromUDPAddrPort (alloc-free).

func (*Conn) SetMulticast

func (c *Conn) SetMulticast(opts MulticastOptions) error

SetMulticast configures the sender's outbound multicast options on its media (and, for the Simple even/odd pair, RTCP) socket: the egress interface, the multicast hop limit (TTL), and loopback. It is a no-op when opts.Group is not a multicast address. Only the options the caller set are applied (TTL 0 and a nil Iface leave the OS default in place).

func (*Conn) WriteMedia

func (c *Conn) WriteMedia(b []byte, dst netip.AddrPort) error

WriteMedia sends a media (RTP) datagram to dst. When DTLS is enabled (Main profile) it seals b as a DTLS application record to the established peer and dst is ignored (the DTLS session is bound to one peer).

func (*Conn) WriteRTCP

func (c *Conn) WriteRTCP(b []byte, dst netip.AddrPort) error

WriteRTCP sends an RTCP datagram to dst.

type MulticastOptions

type MulticastOptions struct {
	// Group is the multicast destination/bind group. A receiver joins it; a
	// sender stamps its egress options when transmitting to it. The zero Addr
	// means "not multicast" (unicast, the default).
	Group netip.Addr
	// Source, when set, selects source-specific multicast (SSM, RFC 4607): a
	// receiver joins the group filtered to this source IP. The zero Addr means
	// any-source multicast (ASM).
	Source netip.Addr
	// Iface is the membership (receiver) or egress (sender) interface; nil lets
	// the OS choose the system default.
	Iface *net.Interface
	// TTL is the sender's multicast hop limit; 0 leaves the OS default (1).
	TTL int
	// Loopback controls whether a sender receives its own multicast on the same
	// host.
	Loopback bool
}

MulticastOptions configures IP-multicast behavior on a Conn. The zero value is "no multicast" — Conn is a plain unicast transport unless these are set.

Jump to

Keyboard shortcuts

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