Documentation Index Fetch the complete documentation index at: https://mintlify.com/moqtail/moqtail/llms.txt
Use this file to discover all available pages before exploring further.
Model
The model module contains all MOQT protocol data structures, message types, and serialization/deserialization logic. It provides type-safe representations of the MOQT Draft 14 specification.
Module Organization
The model is organized into several submodules:
pub mod catalog ; // Catalog data structures
pub mod common ; // Shared types (tuples, varints, locations)
pub mod control ; // Control message types
pub mod data ; // Data stream structures
pub mod error ; // Error types and codes
pub mod extension_header ; // Extension headers
pub mod parameter ; // Setup and message parameters
Control Messages
ControlMessage Enum
The ControlMessage enum represents all MOQT control message types:
use moqtail :: model :: control :: control_message :: ControlMessage ;
pub enum ControlMessage {
// Namespace publishing
PublishNamespace ( Box < PublishNamespace >),
PublishNamespaceOk ( Box < PublishNamespaceOk >),
PublishNamespaceError ( Box < PublishNamespaceError >),
PublishNamespaceCancel ( Box < PublishNamespaceCancel >),
PublishNamespaceDone ( Box < PublishNamespaceDone >),
// Track publishing
Publish ( Box < Publish >),
PublishOk ( Box < PublishOk >),
PublishError ( Box < PublishError >),
PublishDone ( Box < PublishDone >),
// Setup
ClientSetup ( Box < ClientSetup >),
ServerSetup ( Box < ServerSetup >),
// Subscription
Subscribe ( Box < Subscribe >),
SubscribeOk ( Box < SubscribeOk >),
SubscribeError ( Box < SubscribeError >),
SubscribeUpdate ( Box < SubscribeUpdate >),
Unsubscribe ( Box < Unsubscribe >),
// Namespace subscription
SubscribeNamespace ( Box < SubscribeNamespace >),
SubscribeNamespaceOk ( Box < SubscribeNamespaceOk >),
SubscribeNamespaceError ( Box < SubscribeNamespaceError >),
UnsubscribeNamespace ( Box < UnsubscribeNamespace >),
// Fetch
Fetch ( Box < Fetch >),
FetchOk ( Box < FetchOk >),
FetchError ( Box < FetchError >),
FetchCancel ( Box < FetchCancel >),
// Status
TrackStatus ( Box < TrackStatus >),
TrackStatusOk ( Box < TrackStatusOk >),
TrackStatusError ( Box < TrackStatusError >),
// Connection management
Goaway ( Box < GoAway >),
RequestsBlocked ( Box < RequestsBlocked >),
MaxRequestId ( Box < MaxRequestId >),
Switch ( Box < Switch >),
}
Serialization and Deserialization
All control messages implement serialization:
use bytes :: Bytes ;
use moqtail :: model :: error :: ParseError ;
// Serialize a control message
let message = ControlMessage :: Subscribe ( Box :: new ( subscribe ));
let bytes : Bytes = message . serialize () ? ;
// Deserialize from bytes
let mut buffer = bytes ;
let parsed : ControlMessage = ControlMessage :: deserialize ( & mut buffer ) ? ;
match parsed {
ControlMessage :: Subscribe ( sub ) => println! ( "Received subscribe for {}" , sub . track_name),
_ => println! ( "Other message type" ),
}
Setup Messages
ClientSetup
Initiates the MOQT handshake:
use moqtail :: model :: control :: client_setup :: ClientSetup ;
use moqtail :: model :: control :: constant :: DRAFT_14 ;
use moqtail :: model :: common :: pair :: KeyValuePair ;
use bytes :: Bytes ;
// Create client setup with supported versions
let supported_versions = vec! [ DRAFT_14 ];
let setup_parameters = vec! [
KeyValuePair :: try_new_varint ( 0 , 10 ) . unwrap (),
KeyValuePair :: try_new_bytes ( 1 , Bytes :: from_static ( b"client-role" )) . unwrap (),
];
let client_setup = ClientSetup :: new ( supported_versions , setup_parameters );
// Serialize
let bytes = client_setup . serialize () ? ;
// Deserialize
let mut buf = bytes ;
let parsed = ClientSetup :: parse_payload ( & mut buf ) ? ;
ServerSetup
Server’s response to client setup:
use moqtail :: model :: control :: server_setup :: ServerSetup ;
let server_setup = ServerSetup {
selected_version : DRAFT_14 ,
setup_parameters : vec! [
KeyValuePair :: try_new_bytes ( 1 , Bytes :: from_static ( b"relay-server" )) . unwrap (),
],
};
Subscription Messages
Subscribe
Request to subscribe to a track:
use moqtail :: model :: control :: subscribe :: Subscribe ;
use moqtail :: model :: control :: constant :: { FilterType , GroupOrder };
use moqtail :: model :: common :: tuple :: { Tuple , TupleField };
use moqtail :: model :: common :: location :: Location ;
// Subscribe from latest object
let subscribe = Subscribe :: new_latest_object (
request_id : 1 ,
track_namespace : Tuple :: from_utf8_path ( "conference/room1" ),
track_name : TupleField :: from_utf8 ( "video" ),
subscriber_priority : 128 ,
group_order : GroupOrder :: Ascending ,
forward : true ,
subscribe_parameters : vec! [],
);
// Subscribe from specific location
let subscribe = Subscribe :: new_absolute_start (
request_id : 2 ,
track_namespace : Tuple :: from_utf8_path ( "conference/room1" ),
track_name : TupleField :: from_utf8 ( "audio" ),
subscriber_priority : 128 ,
group_order : GroupOrder :: Original ,
forward : false ,
start_location : Location { group : 100 , object : 0 },
subscribe_parameters : vec! [],
);
// Subscribe to a range
let subscribe = Subscribe :: new_absolute_range (
request_id : 3 ,
track_namespace : Tuple :: from_utf8_path ( "conference/room1" ),
track_name : TupleField :: from_utf8 ( "chat" ),
subscriber_priority : 64 ,
group_order : GroupOrder :: Ascending ,
forward : true ,
start_location : Location { group : 50 , object : 0 },
end_group : 100 ,
subscribe_parameters : vec! [],
);
FilterType and GroupOrder
Subscription filtering options:
use moqtail :: model :: control :: constant :: { FilterType , GroupOrder };
// Filter types
let filter = FilterType :: LatestObject ; // Start from latest
let filter = FilterType :: NextGroupStart ; // Start from next group
let filter = FilterType :: AbsoluteStart ; // Start from specific location
let filter = FilterType :: AbsoluteRange ; // Specific range
// Group ordering
let order = GroupOrder :: Original ; // Publisher's order
let order = GroupOrder :: Ascending ; // Ascending group IDs
let order = GroupOrder :: Descending ; // Descending group IDs
Common Types
Tuple and TupleField
Namespace and track name representations:
use moqtail :: model :: common :: tuple :: { Tuple , TupleField };
// Create tuple from path
let namespace = Tuple :: from_utf8_path ( "conference/room1/track1" );
println! ( "Fields: {}" , namespace . fields . len ()); // 3
// Create individual field
let field = TupleField :: from_utf8 ( "video" );
println! ( "Length: {}" , field . len ());
// Build tuple manually
let mut tuple = Tuple :: new ();
tuple . add ( TupleField :: from_utf8 ( "conference" ));
tuple . add ( TupleField :: from_utf8 ( "room42" ));
// Convert to path
let path = tuple . to_utf8_path ();
println! ( "Path: {}" , path ); // "/conference/room42"
// Check prefix
let prefix = Tuple :: from_utf8_path ( "conference" );
assert! ( tuple . starts_with ( & prefix ));
// Serialize/deserialize
let bytes = tuple . serialize () ? ;
let mut buf = bytes ;
let parsed = Tuple :: deserialize ( & mut buf ) ? ;
FullTrackName
Combines namespace and track name:
use moqtail :: model :: data :: full_track_name :: FullTrackName ;
// Create full track name
let namespace = Tuple :: from_utf8_path ( "conference/room1" );
let track_name = TupleField :: from_utf8 ( "video" );
let full_track = FullTrackName :: new ( namespace , track_name ) ? ;
// Or use convenience method
let full_track = FullTrackName :: try_new ( "conference/room1" , "video" ) ? ;
// Display
println! ( "{}" , full_track ); // "conference-room1--video"
// Serialize/deserialize
let bytes = full_track . serialize () ? ;
let mut buf = bytes ;
let parsed = FullTrackName :: deserialize ( & mut buf ) ? ;
Location
Identifies a specific object in a track:
use moqtail :: model :: common :: location :: Location ;
let loc = Location {
group : 42 ,
object : 10 ,
};
// Serialize/deserialize
let bytes = loc . serialize () ? ;
let mut buf = bytes ;
let parsed = Location :: deserialize ( & mut buf ) ? ;
KeyValuePair
Parameters for setup and other messages:
use moqtail :: model :: common :: pair :: KeyValuePair ;
use bytes :: Bytes ;
// Varint value
let param = KeyValuePair :: try_new_varint ( 0 , 1000 ) ? ;
// Bytes value
let param = KeyValuePair :: try_new_bytes (
1 ,
Bytes :: from_static ( b"custom-value" )
) ? ;
// Serialize/deserialize
let bytes = param . serialize () ? ;
let mut buf = bytes ;
let parsed = KeyValuePair :: deserialize ( & mut buf ) ? ;
Data Structures
Track
Represents a media track:
use moqtail :: model :: data :: track :: Track ;
use moqtail :: model :: data :: full_track_name :: FullTrackName ;
use moqtail :: model :: data :: constant :: ObjectForwardingPreference ;
use std :: collections :: BTreeMap ;
let track = Track {
full_track_name : FullTrackName :: try_new ( "conference/room1" , "video" ) ? ,
groups : BTreeMap :: new (),
forwarding_preference : ObjectForwardingPreference :: StreamPerObject ,
};
Group and Object
Organize media data:
use moqtail :: model :: data :: group :: Group ;
use moqtail :: model :: data :: object :: Object ;
// Groups contain objects
let group = Group {
id : 42 ,
objects : BTreeMap :: new (),
};
// Objects contain media data
let object = Object {
id : 10 ,
payload : bytes ,
};
Error Types
ParseError
Errors during message parsing:
use moqtail :: model :: error :: ParseError ;
match result {
Err ( ParseError :: NotEnoughBytes { context , needed , available }) => {
eprintln! ( "Need {} bytes, have {}, context: {}" , needed , available , context );
}
Err ( ParseError :: ProtocolViolation { context , details }) => {
eprintln! ( "Protocol violation in {}: {}" , context , details );
}
Err ( ParseError :: CastingError { context , from_type , to_type , details }) => {
eprintln! ( "Cast error {} -> {} in {}: {}" , from_type , to_type , context , details );
}
Err ( ParseError :: TrackNameError { context , details }) => {
eprintln! ( "Track name error in {}: {}" , context , details );
}
Ok ( value ) => { /* use value */ }
}
TerminationCode
Connection termination reasons:
use moqtail :: model :: error :: TerminationCode ;
let error = TerminationCode :: ProtocolViolation ;
println! ( "Error code: {}" , error . to_u32 ());
println! ( "Error JSON: {}" , error . to_json ());
match error {
TerminationCode :: NoError => { /* clean close */ }
TerminationCode :: InternalError => { /* internal error */ }
TerminationCode :: Unauthorized => { /* auth failed */ }
TerminationCode :: ProtocolViolation => { /* protocol error */ }
TerminationCode :: ControlMessageTimeout => { /* timeout */ }
TerminationCode :: VersionNegotiationFailed => { /* version mismatch */ }
_ => { /* other errors */ }
}
Message Examples
Complete Message Roundtrip
Example showing serialization and deserialization:
use moqtail :: model :: control :: publish_namespace :: PublishNamespace ;
use moqtail :: model :: control :: control_message :: ControlMessage ;
use moqtail :: model :: common :: tuple :: Tuple ;
use moqtail :: model :: common :: pair :: KeyValuePair ;
use bytes :: Bytes ;
// Create message
let request_id = 12345 ;
let track_namespace = Tuple :: from_utf8_path ( "conference/room1" );
let parameters = vec! [
KeyValuePair :: try_new_varint ( 0 , 10 ) . unwrap (),
KeyValuePair :: try_new_bytes ( 1 , Bytes :: from_static ( b"metadata" )) . unwrap (),
];
let announce = PublishNamespace {
request_id ,
track_namespace ,
parameters ,
};
// Serialize
let mut buf = announce . serialize () . unwrap ();
// Deserialize
let deserialized = ControlMessage :: deserialize ( & mut buf ) . unwrap ();
// Match and verify
if let ControlMessage :: PublishNamespace ( deserialized_announce ) = deserialized {
assert_eq! ( * deserialized_announce , announce );
println! ( "Roundtrip successful!" );
}
Constants
Protocol Constants
Important MOQT constants:
use moqtail :: model :: control :: constant :: DRAFT_14 ;
// Version
const MOQT_VERSION : u32 = DRAFT_14 ;
// Error codes available in various enums:
// - PublishNamespaceErrorCode
// - PublishErrorCode
// - SubscribeErrorCode
// - FetchErrorCode
Best Practices
Type Safety : Always use the type-safe structures instead of raw bytes. The model layer ensures protocol correctness at compile time.
Error Handling : Match on specific error variants to handle different failure scenarios appropriately.
Validation : The model layer validates constraints (e.g., max namespace length, required fields) during construction and deserialization.
Next Steps
Transport Layer Learn how messages are sent and received
Client Guide Build clients using these message types
Relay Guide Implement relay logic with the model layer