Skip to main content

moqtap_client/draft15/session/
setup.rs

1use moqtap_codec::draft15::message::{ClientSetup, ServerSetup};
2use moqtap_codec::kvp::KeyValuePair;
3use moqtap_codec::varint::VarInt;
4
5/// The PATH setup parameter. It is the one setup parameter whose sender is
6/// restricted, and the restriction runs one way: PATH is the client's.
7const PATH: u64 = 0x01;
8
9/// Errors from setup message validation.
10#[derive(Debug, thiserror::Error, PartialEq, Eq)]
11pub enum SetupError {
12    /// A required setup parameter is missing.
13    #[error("missing required parameter: {0}")]
14    MissingParameter(
15        /// Name of the missing parameter.
16        &'static str,
17    ),
18    /// A setup parameter was sent by the endpoint that may not send it.
19    #[error("setup parameter {0:#x} may not be sent by this endpoint")]
20    WrongParameterRole(
21        /// Key of the offending parameter.
22        u64,
23    ),
24    /// A PATH parameter was offered on a session that is not native QUIC.
25    #[error("PATH may not be used when WebTransport is used")]
26    PathOverWebTransport,
27}
28
29/// Validate a CLIENT_SETUP message.
30///
31/// Section 9.3.1.3 puts no role restriction on MAX_REQUEST_ID: it
32/// "communicates an initial value for the Maximum Request ID to the receiving
33/// endpoint", which is something either endpoint may do, and a client that
34/// grants the server a request budget during setup is doing exactly that. PATH
35/// is the restricted parameter, and it belongs to the client, so a
36/// CLIENT_SETUP is where it is legal.
37pub fn validate_client_setup(_msg: &ClientSetup) -> Result<(), SetupError> {
38    Ok(())
39}
40
41/// Validate a SERVER_SETUP message.
42///
43/// Section 9.3.1.2 on PATH: "It MUST NOT be used by the server, or when
44/// WebTransport is used", and a PATH received from the server closes the
45/// session with INVALID_PATH. Nothing else in a SERVER_SETUP is restricted by
46/// sender.
47///
48/// # Errors
49///
50/// [`SetupError::WrongParameterRole`] if the server sent a PATH.
51pub fn validate_server_setup(msg: &ServerSetup) -> Result<(), SetupError> {
52    if has_path(&msg.parameters) {
53        return Err(SetupError::WrongParameterRole(PATH));
54    }
55    Ok(())
56}
57
58/// Refuse a PATH parameter on a session that is not native QUIC.
59///
60/// The same sentence in Section 9.3.1.2 forbids PATH "when WebTransport is
61/// used" and closes the session with INVALID_PATH on one received there. Which
62/// transport carries the session is known to the connection and not to the
63/// endpoint, so this is a separate call rather than part of
64/// `validate_client_setup`.
65///
66/// # Errors
67///
68/// [`SetupError::PathOverWebTransport`] if a PATH is offered over
69/// WebTransport.
70pub fn validate_client_path_transport(
71    parameters: &[KeyValuePair],
72    over_webtransport: bool,
73) -> Result<(), SetupError> {
74    if over_webtransport && has_path(parameters) {
75        return Err(SetupError::PathOverWebTransport);
76    }
77    Ok(())
78}
79
80fn has_path(parameters: &[KeyValuePair]) -> bool {
81    let path = VarInt::from_u64(PATH).unwrap();
82    parameters.iter().any(|p| p.key == path)
83}