moq-rs/moq-transport/src/setup/version.rs

156 lines
5.3 KiB
Rust

use crate::coding::{Decode, DecodeError, Encode, EncodeError, VarInt};
use crate::coding::{AsyncRead, AsyncWrite};
use std::ops::Deref;
/// A version number negotiated during the setup.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Version(pub VarInt);
impl Version {
/// https://www.ietf.org/archive/id/draft-ietf-moq-transport-00.html
pub const DRAFT_00: Version = Version(VarInt::from_u32(0xff000000));
/// https://www.ietf.org/archive/id/draft-ietf-moq-transport-01.html
pub const DRAFT_01: Version = Version(VarInt::from_u32(0xff000001));
/// Fork of draft-ietf-moq-transport-00.
///
/// Rough list of differences:
///
/// # Messages
/// - Messages are sent over a control stream or a data stream.
/// - Data streams: each unidirectional stream contains a single OBJECT message.
/// - Control stream: a (client-initiated) bidirectional stream containing SETUP and then all other messages.
/// - Messages do not contain a length; unknown messages are fatal.
///
/// # SETUP
/// - SETUP is split into SETUP_CLIENT and SETUP_SERVER with separate IDs.
/// - SETUP uses version `0xff00` for draft-00.
/// - SETUP no longer contains optional parameters; all are encoded in order and possibly zero.
/// - SETUP `role` indicates the role of the sender, not the role of the server.
/// - SETUP `path` field removed; use WebTransport for path.
///
/// # SUBSCRIBE
/// - SUBSCRIBE `full_name` is split into separate `namespace` and `name` fields.
/// - SUBSCRIBE no longer contains optional parameters; all are encoded in order and possibly zero.
/// - SUBSCRIBE no longer contains the `auth` parameter; use WebTransport for auth.
/// - SUBSCRIBE no longer contains the `group` parameter; concept no longer exists.
/// - SUBSCRIBE contains the `id` instead of SUBSCRIBE_OK.
/// - SUBSCRIBE_OK and SUBSCRIBE_ERROR reference the subscription `id` the instead of the track `full_name`.
/// - SUBSCRIBE_ERROR was renamed to SUBSCRIBE_RESET, sent by publisher to terminate a SUBSCRIBE.
/// - SUBSCRIBE_STOP was added, sent by the subscriber to terminate a SUBSCRIBE.
/// - SUBSCRIBE_OK no longer has `expires`.
///
/// # ANNOUNCE
/// - ANNOUNCE no longer contains optional parameters; all are encoded in order and possibly zero.
/// - ANNOUNCE no longer contains the `auth` field; use WebTransport for auth.
/// - ANNOUNCE_ERROR was renamed to ANNOUNCE_RESET, sent by publisher to terminate an ANNOUNCE.
/// - ANNOUNCE_STOP was added, sent by the subscriber to terminate an ANNOUNCE.
///
/// # OBJECT
/// - OBJECT uses a dedicated QUIC stream.
/// - OBJECT has no size and continues until stream FIN.
/// - OBJECT `priority` is a i32 instead of a varint. (for practical reasons)
/// - OBJECT `expires` was added, a varint in seconds.
/// - OBJECT `group` was removed.
///
/// # GROUP
/// - GROUP concept was removed, replaced with OBJECT as a QUIC stream.
pub const KIXEL_00: Version = Version(VarInt::from_u32(0xbad00));
/// Fork of draft-ietf-moq-transport-01.
///
/// Most of the KIXEL_00 changes made it into the draft, or were reverted.
/// This was only used for a short time until extensions were created.
///
/// - SUBSCRIBE contains a separate track namespace and track name field (accidental revert). [#277](https://github.com/moq-wg/moq-transport/pull/277)
/// - SUBSCRIBE contains the `track_id` instead of SUBSCRIBE_OK. [#145](https://github.com/moq-wg/moq-transport/issues/145)
/// - SUBSCRIBE_* reference `track_id` the instead of the `track_full_name`. [#145](https://github.com/moq-wg/moq-transport/issues/145)
/// - OBJECT `priority` is still a VarInt, but the max value is a u32 (implementation reasons)
/// - OBJECT messages within the same `group` MUST be on the same QUIC stream.
pub const KIXEL_01: Version = Version(VarInt::from_u32(0xbad01));
}
impl From<VarInt> for Version {
fn from(v: VarInt) -> Self {
Self(v)
}
}
impl From<Version> for VarInt {
fn from(v: Version) -> Self {
v.0
}
}
impl Version {
/// Decode the version number.
pub async fn decode<R: AsyncRead>(r: &mut R) -> Result<Self, DecodeError> {
let v = VarInt::decode(r).await?;
Ok(Self(v))
}
/// Encode the version number.
pub async fn encode<W: AsyncWrite>(&self, w: &mut W) -> Result<(), EncodeError> {
self.0.encode(w).await?;
Ok(())
}
}
/// A list of versions in arbitrary order.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Versions(Vec<Version>);
#[async_trait::async_trait]
impl Decode for Versions {
/// Decode the version list.
async fn decode<R: AsyncRead>(r: &mut R) -> Result<Self, DecodeError> {
let count = VarInt::decode(r).await?.into_inner();
let mut vs = Vec::new();
for _ in 0..count {
let v = Version::decode(r).await?;
vs.push(v);
}
Ok(Self(vs))
}
}
#[async_trait::async_trait]
impl Encode for Versions {
/// Encode the version list.
async fn encode<W: AsyncWrite>(&self, w: &mut W) -> Result<(), EncodeError> {
let size: VarInt = self.0.len().try_into()?;
size.encode(w).await?;
for v in &self.0 {
v.encode(w).await?;
}
Ok(())
}
}
impl Deref for Versions {
type Target = Vec<Version>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<Vec<Version>> for Versions {
fn from(vs: Vec<Version>) -> Self {
Self(vs)
}
}
impl<const N: usize> From<[Version; N]> for Versions {
fn from(vs: [Version; N]) -> Self {
Self(vs.to_vec())
}
}