moqtap_client/draft16/session/setup.rs
1use moqtap_codec::draft16::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}