Client

moqt.Client manages client-side operations for the MoQ protocol. It establishes and maintains sessions, handling the lifecycle.

Overview
func main() {
    // Create a new client
	client := moqt.Client{
		// Set client options here
	}

	// Dial and establish a session with the server
	sess, err := client.Dial(context.Background(), "https://[addr]:[port]/[path]", nil)
	if err != nil {
		log.Fatalf("Failed to dial: %v", err)
	}
	defer sess.CloseWithError(moqt.NoErrorCode, "Client shutting down")

	// Use the session (e.g., subscribe to tracks, receive announcements)

	// Gracefully shut down the client when done
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	if err := client.Shutdown(ctx); err != nil {
		log.Printf("Client shutdown error: %v", err)
	}
}

Initialize a Client

There is no dedicated function (such as a constructor) for initializing a client. Users define the struct directly and assign values to its fields as needed.

    client := moqt.Client{
		// Set client options here
	}

Configuration

The following table describes the public fields of the moqt.Client struct:

FieldTypeDescription
TLSConfig*tls.ConfigTLS configuration for secure connections
QUICConfig*quic.ConfigQUIC protocol configuration
Config*moqt.ConfigMOQ protocol configuration
DialQUICFuncquic.DialAddrFuncFunction to dial QUIC connection
DialWebTransportFuncwebtransport.DialAddrFuncFunction to dial WebTransport connection
Logger*slog.LoggerLogger for client events and errors

quic-go/quic-go is used internally as the default QUIC implementation when relevant fields which is set for customization are not set or nil.

quic-go/quic-go
Loading...
- -

To use a custom QUIC implementation, you need to provide your own implementation of the quic.DialAddrFunc. (moqt.Client).DialQUICFunc field is set, it is used to dial QUIC connections instead of the default implementation.

type Client struct {
    // ...
	DialQUICFunc quic.DialAddrFunc
    // ...
}

quic-go/webtransport-go is used internally as the default WebTransport implementation when relevant fields which is set for customization are not set or nil.

quic-go/webtransport-go
Loading...
- -

To use a custom WebTransport implementation, you need to provide your own implementation of the webtransport.DialAddrFunc. (moqt.Client).DialWebTransportFunc field is set, it is used to dial WebTransport connections instead of the default implementation.

type Client struct {
    // ...
	DialWebTransportFunc webtransport.DialAddrFunc
    // ...
}

Dial and Establish Session

Clients can initiate a QUIC connection and establish a MOQ session with a server using the (*moqt.Client).Dial method.

	var mux *TrackMux
	sess, err := client.Dial(ctx, "https://[addr]:[port]/[path]", mux)
	if err != nil {
		// Handle error
		return
	}

	// Handle session

Note: Nil TrackMux

When mux is set to nil, the moqt.DefaultTrackMux will be used by default. Ensure that the mux is properly configured for your use case to avoid unexpected behavior.

Shutting Down a Client

Clients can shut down in two ways: immediate or graceful.

Immediate Shutdown

(moqt.Client).Close method forcefully terminates all sessions and releases resources. Use cautiously as it may interrupt operations.

    client.Close() // Immediate shutdown

Graceful Shutdown

(moqt.Client).Shutdown method waits for sessions to close naturally, or forces termination on timeout.

    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()
    err := client.Shutdown(ctx)
    if err != nil {
        // Handle forced termination
    }

Note: GOAWAY message

The current implementation does not send a GOAWAY message during shutdown. Immediate session closure occurs when the context is canceled. This will be updated once the GOAWAY message specification is finalized.

📝 Future Work

  • Implement GOAWAY message: (#XXX)