tokio_quiche/http3/driver/
server.rs1use std::ops::Deref;
28use std::sync::Arc;
29
30use tokio::sync::mpsc;
31
32use super::datagram;
33use super::DriverHooks;
34use super::H3Command;
35use super::H3ConnectionError;
36use super::H3ConnectionResult;
37use super::H3Controller;
38use super::H3Driver;
39use super::H3Event;
40use super::InboundHeaders;
41use super::IncomingH3Headers;
42use super::StreamCtx;
43use super::STREAM_CAPACITY;
44use crate::http3::settings::Http3Settings;
45use crate::http3::settings::Http3SettingsEnforcer;
46use crate::http3::settings::Http3TimeoutType;
47use crate::http3::settings::TimeoutKey;
48use crate::quic::HandshakeInfo;
49use crate::quic::QuicCommand;
50use crate::quic::QuicheConnection;
51
52pub type ServerH3Driver = H3Driver<ServerHooks>;
56pub type ServerH3Controller = H3Controller<ServerHooks>;
59pub type ServerEventStream = mpsc::UnboundedReceiver<ServerH3Event>;
63
64#[derive(Clone, Debug)]
65pub struct RawPriorityValue(Vec<u8>);
66
67impl From<Vec<u8>> for RawPriorityValue {
68 fn from(value: Vec<u8>) -> Self {
69 RawPriorityValue(value)
70 }
71}
72
73impl Deref for RawPriorityValue {
74 type Target = [u8];
75
76 fn deref(&self) -> &Self::Target {
77 &self.0
78 }
79}
80
81#[derive(Clone, Debug)]
83pub struct IsInEarlyData(bool);
84
85impl IsInEarlyData {
86 fn new(is_in_early_data: bool) -> Self {
87 IsInEarlyData(is_in_early_data)
88 }
89}
90
91impl Deref for IsInEarlyData {
92 type Target = bool;
93
94 fn deref(&self) -> &Self::Target {
95 &self.0
96 }
97}
98
99#[derive(Debug)]
101pub enum ServerH3Event {
102 Core(H3Event),
103
104 Headers {
105 incoming_headers: IncomingH3Headers,
106 priority: Option<RawPriorityValue>,
108 is_in_early_data: IsInEarlyData,
109 },
110}
111
112impl From<H3Event> for ServerH3Event {
113 fn from(ev: H3Event) -> Self {
114 match ev {
115 H3Event::IncomingHeaders(incoming_headers) => {
116 Self::Headers {
122 incoming_headers,
123 priority: None,
124 is_in_early_data: IsInEarlyData::new(false),
125 }
126 },
127 _ => Self::Core(ev),
128 }
129 }
130}
131
132#[derive(Debug)]
134pub enum ServerH3Command {
135 Core(H3Command),
136}
137
138impl From<H3Command> for ServerH3Command {
139 fn from(cmd: H3Command) -> Self {
140 Self::Core(cmd)
141 }
142}
143
144impl From<QuicCommand> for ServerH3Command {
145 fn from(cmd: QuicCommand) -> Self {
146 Self::Core(H3Command::QuicCmd(cmd))
147 }
148}
149
150const PRE_HEADERS_BOOSTED_PRIORITY_URGENCY: u8 = 64;
154const PRE_HEADERS_BOOSTED_PRIORITY_INCREMENTAL: bool = false;
157
158pub struct ServerHooks {
159 settings_enforcer: Http3SettingsEnforcer,
161 requests: u64,
163
164 post_accept_timeout: Option<TimeoutKey>,
167 extended_connect_enabled: bool,
170}
171
172impl ServerHooks {
173 fn handle_request(
178 driver: &mut H3Driver<Self>, qconn: &mut QuicheConnection,
179 headers: InboundHeaders,
180 ) -> H3ConnectionResult<()> {
181 let InboundHeaders {
182 stream_id,
183 headers,
184 has_body,
185 } = headers;
186
187 if driver.stream_map.contains_key(&stream_id) {
191 return Ok(());
192 }
193
194 let (mut stream_ctx, send, recv) = StreamCtx::new(
195 stream_id,
196 STREAM_CAPACITY,
197 driver.ready_stream_sender.clone(),
198 );
199
200 if driver.hooks.extended_connect_enabled() {
207 if let Some(flow_id) =
208 datagram::extract_quarter_stream_id(stream_id, &headers)
209 {
210 let _ = driver.get_or_insert_flow(flow_id)?;
211 stream_ctx.associated_dgram_flow_id = Some(flow_id);
212 }
213 }
214
215 let latest_priority_update: Option<RawPriorityValue> = driver
216 .conn_mut()?
217 .take_last_priority_update(stream_id)
218 .ok()
219 .map(|v| v.into());
220
221 qconn
225 .stream_priority(
226 stream_id,
227 PRE_HEADERS_BOOSTED_PRIORITY_URGENCY,
228 PRE_HEADERS_BOOSTED_PRIORITY_INCREMENTAL,
229 )
230 .ok();
231
232 let headers = IncomingH3Headers {
233 stream_id,
234 headers,
235 send,
236 recv,
237 read_fin: !has_body,
238 h3_audit_stats: Arc::clone(&stream_ctx.audit_stats),
239 };
240
241 stream_ctx.wait_for_recv();
242 driver.insert_stream(stream_id, stream_ctx);
243
244 driver.process_writable_stream(qconn, stream_id)?;
250
251 driver
252 .h3_event_sender
253 .send(ServerH3Event::Headers {
254 incoming_headers: headers,
255 priority: latest_priority_update,
256 is_in_early_data: IsInEarlyData::new(qconn.is_in_early_data()),
257 })
258 .map_err(|_| H3ConnectionError::ControllerWentAway)?;
259 driver.hooks.requests += 1;
260
261 Ok(())
262 }
263}
264
265#[allow(private_interfaces)]
266impl DriverHooks for ServerHooks {
267 type Command = ServerH3Command;
268 type Event = ServerH3Event;
269
270 fn new(settings: &Http3Settings) -> Self {
271 Self {
272 settings_enforcer: settings.into(),
273 requests: 0,
274 post_accept_timeout: None,
275 extended_connect_enabled: settings.enable_extended_connect,
276 }
277 }
278
279 fn extended_connect_enabled(&self) -> bool {
280 self.extended_connect_enabled
281 }
282
283 fn conn_established(
284 driver: &mut H3Driver<Self>, qconn: &mut QuicheConnection,
285 handshake_info: &HandshakeInfo,
286 ) -> H3ConnectionResult<()> {
287 assert!(
288 qconn.is_server(),
289 "ServerH3Driver requires a server-side QUIC connection"
290 );
291
292 if let Some(post_accept_timeout) =
293 driver.hooks.settings_enforcer.post_accept_timeout()
294 {
295 let remaining = post_accept_timeout
296 .checked_sub(handshake_info.elapsed())
297 .ok_or(H3ConnectionError::PostAcceptTimeout)?;
298
299 let key = driver
300 .hooks
301 .settings_enforcer
302 .add_timeout(Http3TimeoutType::PostAccept, remaining);
303 driver.hooks.post_accept_timeout = Some(key);
304 }
305
306 Ok(())
307 }
308
309 fn headers_received(
310 driver: &mut H3Driver<Self>, qconn: &mut QuicheConnection,
311 headers: InboundHeaders,
312 ) -> H3ConnectionResult<()> {
313 if driver
314 .hooks
315 .settings_enforcer
316 .enforce_requests_limit(driver.hooks.requests)
317 {
318 let _ =
319 qconn.close(true, quiche::h3::WireErrorCode::NoError as u64, &[]);
320 return Ok(());
321 }
322
323 if let Some(timeout) = driver.hooks.post_accept_timeout.take() {
324 driver.hooks.settings_enforcer.cancel_timeout(timeout);
327 }
328
329 Self::handle_request(driver, qconn, headers)
330 }
331
332 fn stream_recv_closed(_driver: &mut H3Driver<Self>, _stream_id: u64) {}
333
334 fn stream_closed(driver: &mut H3Driver<Self>, stream_id: u64) {
335 let _ = driver
336 .h3_event_sender
337 .send(H3Event::StreamClosed { stream_id }.into());
338 }
339
340 fn conn_command(
341 driver: &mut H3Driver<Self>, qconn: &mut QuicheConnection,
342 cmd: Self::Command,
343 ) -> H3ConnectionResult<()> {
344 let ServerH3Command::Core(cmd) = cmd;
345 driver.handle_core_command(qconn, cmd)
346 }
347
348 fn has_wait_action(driver: &mut H3Driver<Self>) -> bool {
349 driver.hooks.settings_enforcer.has_pending_timeouts()
350 }
351
352 async fn wait_for_action(
353 &mut self, qconn: &mut QuicheConnection,
354 ) -> H3ConnectionResult<()> {
355 self.settings_enforcer.enforce_timeouts(qconn).await?;
356 Err(H3ConnectionError::PostAcceptTimeout)
357 }
358}