1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use crate::proto::{TransportParams, DEFAULT_MAX_RECORD_SIZE};
use crate::Version;
/// How the application-level protocol is determined for a session.
#[derive(Debug, Clone, Default)]
pub enum Protocol {
/// No application protocol.
#[default]
None,
/// Advertise these protocols and negotiate one in-band, via the QMux
/// `application_protocols` transport parameter (preference order).
///
/// For transports without ALPN (TCP, Unix sockets). Both peers must opt in:
/// receiving the parameter while *not* in this mode is a protocol error.
/// The agreed protocol is surfaced by
/// [`Session::protocol`](web_transport_trait::Session::protocol) /
/// [`Session::negotiated`](crate::Session::negotiated) once params arrive.
Negotiate(Vec<String>),
/// Already negotiated out of band (TLS / WebSocket ALPN). Reported as-is;
/// the `application_protocols` parameter is never sent, and receiving it is
/// a protocol error.
Negotiated(String),
}
/// Configuration for a QMux session.
#[derive(Debug, Clone)]
pub struct Config {
/// Wire format version.
pub version: Version,
/// How the application protocol is determined. See [`Protocol`].
pub protocol: Protocol,
/// Max concurrent bidirectional streams the peer can open.
pub max_streams_bidi: u64,
/// Max concurrent unidirectional streams the peer can open.
pub max_streams_uni: u64,
/// Connection-level receive window in bytes.
pub max_data: u64,
/// Per-stream receive window for bidi streams we initiate.
pub max_stream_data_bidi_local: u64,
/// Per-stream receive window for bidi streams the peer initiates.
pub max_stream_data_bidi_remote: u64,
/// Per-stream receive window for uni streams.
pub max_stream_data_uni: u64,
/// Idle timeout in milliseconds (0 = disabled). Only used in QMux01.
pub max_idle_timeout: u64,
/// Maximum QMux Record size in bytes (draft-01). Default: 16382.
pub max_record_size: u64,
}
impl Default for Config {
fn default() -> Self {
Self {
version: Version::QMux01,
protocol: Protocol::None,
max_streams_bidi: 100,
max_streams_uni: 100,
max_data: 1_048_576, // 1 MB
max_stream_data_bidi_local: 262_144, // 256 KB
max_stream_data_bidi_remote: 262_144, // 256 KB
max_stream_data_uni: 262_144, // 256 KB
max_idle_timeout: 30_000, // 30 seconds
max_record_size: DEFAULT_MAX_RECORD_SIZE,
}
}
}
impl Config {
/// Create a config with default flow control values and no application
/// protocol. Set [`Config::protocol`] to negotiate one.
pub fn new(version: Version) -> Self {
Self {
version,
..Default::default()
}
}
/// Create a config whose protocol was already negotiated out of band
/// (TLS / WebSocket ALPN). `protocol` is the chosen name, or `None`.
pub fn negotiated(version: Version, protocol: Option<String>) -> Self {
Self {
protocol: match protocol {
Some(name) => Protocol::Negotiated(name),
None => Protocol::None,
},
..Self::new(version)
}
}
/// Convert to wire-format transport parameters.
pub(crate) fn to_transport_params(&self) -> TransportParams {
TransportParams {
max_idle_timeout: self.max_idle_timeout,
initial_max_data: self.max_data,
initial_max_stream_data_bidi_local: self.max_stream_data_bidi_local,
initial_max_stream_data_bidi_remote: self.max_stream_data_bidi_remote,
initial_max_stream_data_uni: self.max_stream_data_uni,
initial_max_streams_bidi: self.max_streams_bidi,
initial_max_streams_uni: self.max_streams_uni,
max_record_size: self.max_record_size,
// Only advertise protocols when negotiating in-band; TLS/WS already
// chose one via ALPN and must not send this parameter.
protocols: match &self.protocol {
Protocol::Negotiate(list) => list.clone(),
Protocol::None | Protocol::Negotiated(_) => Vec::new(),
},
}
}
}