A MOQ Session is established when a client dials a server (via moqt.Dialer) or a server accepts a connection (via moqt.Handler). The session manages subscriptions, announcements, fetches, and probes over the underlying QUIC connection.
type Session struct { // contains filtered or unexported fields}func (s *Session) Subscribe(ctx context.Context, path BroadcastPath, name TrackName, config *SubscribeConfig) (*TrackReader, error)func (s *Session) AcceptAnnounce(prefix string) (*AnnouncementReader, error)func (s *Session) Fetch(req *FetchRequest) (*GroupReader, error)func (s *Session) TrackInfo(ctx context.Context, path BroadcastPath, name TrackName) (*PublishInfo, error)func (s *Session) Probe(targetBitrate uint64) (<-chan ProbeResult, error)func (s *Session) ProbeTargets() <-chan ProbeResultfunc (s *Session) Stats() SessionStatsfunc (s *Session) CloseWithError(code SessionErrorCode, msg string) errorfunc (s *Session) Context() context.Contextfunc (s *Session) ConnectionState() ConnectionStatefunc (s *Session) LocalAddr() net.Addrfunc (s *Session) RemoteAddr() net.Addr
Outgoing requests such as subscribing to tracks, fetching specific groups, probing bitrate, or discovering available tracks are handled by the session.
Session.RequestURI returns the session’s request URI as received, like Go’s
http.Request.RequestURI — the path, plus ? and the query when there is one, with
no scheme or host — on either transport binding and on either side of the session:
func (h *HandlerImpl) ServeMOQ(sess *moqt.Session) { path := sess.RequestURI() // path == "/live/alice" for a client that dialed // moqt://host/live/alice or https://host/live/alice}
When the request has a query, it follows the path after ?, as in a request URI:
"/live/alice?jwt=x". Split them with url.Parse:
A query commonly carries a credential, so avoid logging the whole value.The path is resolved by the binding before the session is constructed, so it is
available immediately — you never wait on the peer’s SETUP to read it:
WebTransport: the path is the HTTP request’s path and query as received
(r.URL.RequestURI()), resolved by the HTTP handshake. It is also still available directly on the *http.Request in
your http.Handler, which is where you route with http.ServeMux.
Native QUIC: native QUIC has no handshake-time request URI, so the client
conveys the path in its SETUP message, as the mandatory Path parameter, with ?
and the query appended when there is one. A
server-side router reads it before constructing the session; a SETUP that omits
it, or whose path is not rooted at /, is rejected.
A path is always rooted at / — dialing moqt://host or https://host with no
path yields "/". RequestURI returns "" only for a session constructed without a
binding-supplied path, which the Dialer and Server entry points never produce.
Session.RequestURI is the session’s request URI, which selects a server-side
endpoint. It is unrelated to BroadcastPath, which identifies a broadcast
within an established session — which is why the accessor is named after the
request URI and not Path: in this package “path” already means BroadcastPath.
Session.TrackInfo opens a Track Stream and requests a track’s immutable
publisher properties (TRACK_INFO) — priority, ordering preference, max
latency, and the Timescale needed to interpret frame timestamps — without
subscribing to it. The returned properties are fixed for the lifetime of the
track and should be cached by the caller.
A publisher can customize the properties a subscriber sees in TRACK_INFO by
implementing TrackInfoProvider on its TrackHandler; see
Producing a Track.The values are zero when the current transport does not expose the corresponding metrics, such as some WebTransport browser sessions.
Incoming requests, such as track subscriptions and discovery broadcasts, are handled internally by the session’s moqt.TrackMux, not directly by the moqt.Session struct. Therefore, there are no dedicated methods for these requests on moqt.Session.
To explicitly close a session due to protocol violations, errors, or other reasons, use the Session.CloseWithError method. This closes all associated streams.
func (s *Session) CloseWithError(code SessionErrorCode, msg string) error
code: Error code (e.g., from built-in codes)
msg: Descriptive message
Prefer reserved error codes for standard reasons. See Built-in Error Codes for details.