1use std::{
19 future::Future,
20 pin::Pin,
21 sync::{atomic::AtomicBool, Arc},
22 task::{Context, Poll},
23 time::Duration,
24};
25
26use bytes::Bytes;
27use futures_util::{pin_mut, FutureExt};
28use http::{Request, Response, StatusCode};
29use http_body::Body;
30use rustc_hash::{FxHashMap, FxHashSet};
31use tokio_util::sync::CancellationToken;
32
33use super::codec::{
34 Frame, FrameDecoder, FrameWriter, Setting, CLIENT_PREFACE, DEFAULT_INITIAL_WINDOW_SIZE,
35 DEFAULT_MAX_FRAME_SIZE, MAX_FRAME_SIZE_LIMIT,
36};
37use super::date::DateCache;
38use super::error::Reason;
39use super::hpack::{Decoder as HpackDecoder, Encoder, Header as HpackHeader, HpackError};
40use super::sanitize_response;
41use super::stream::{
42 BodyMsg, H2Body, MalformedRequest, ParsedRequest, StreamDriver, StreamEntry, StreamMsg,
43};
44use crate::early_hints::EarlyHints;
45use crate::Incoming;
46
47#[derive(Debug, Clone, Copy)]
49pub struct ConnectionOptions {
50 pub send_continue_response: bool,
53 pub send_date_header: bool,
55 pub max_concurrent_streams: u32,
57 pub initial_stream_window_size: u32,
59 pub initial_connection_window_size: u32,
61 pub max_frame_size: u32,
63 pub max_header_list_size: u32,
65 pub enable_connect_protocol: bool,
67 pub idle_timeout: Option<Duration>,
70}
71
72impl Default for ConnectionOptions {
73 #[inline]
74 fn default() -> Self {
75 ConnectionOptions {
76 send_continue_response: false,
77 send_date_header: true,
78 max_concurrent_streams: 100,
79 initial_stream_window_size: DEFAULT_INITIAL_WINDOW_SIZE,
80 initial_connection_window_size: DEFAULT_INITIAL_WINDOW_SIZE,
81 max_frame_size: DEFAULT_MAX_FRAME_SIZE as u32,
82 max_header_list_size: u32::MAX,
83 enable_connect_protocol: false,
84 idle_timeout: None,
85 }
86 }
87}
88
89#[derive(Debug, Clone, Copy, PartialEq, Eq)]
93pub struct PeerSettings {
94 pub(crate) header_table_size: u32,
95 pub(crate) enable_push: u32,
96 pub(crate) initial_window_size: u32,
97 pub(crate) max_frame_size: usize,
98 #[allow(dead_code)]
100 pub(crate) max_header_list_size: u32,
101}
102
103impl Default for PeerSettings {
104 #[inline]
105 fn default() -> Self {
106 PeerSettings {
107 header_table_size: 4096,
108 enable_push: 1,
109 initial_window_size: DEFAULT_INITIAL_WINDOW_SIZE,
110 max_frame_size: DEFAULT_MAX_FRAME_SIZE,
111 max_header_list_size: u32::MAX,
112 }
113 }
114}
115
116pub struct Connection<Io> {
122 io: Io,
123 decoder: FrameDecoder,
124 writer: FrameWriter,
125 out: Vec<u8>,
126 encoder: Encoder,
129 request_decoder: HpackDecoder,
132 peer: PeerSettings,
134 #[allow(dead_code)]
137 local: PeerSettings,
138 preface_timeout: Option<Duration>,
141 streams: FxHashMap<u32, StreamEntry>,
143 conn_window: i64,
146 closed_streams: FxHashSet<u32>,
150 #[allow(dead_code)]
152 opts: ConnectionOptions,
153 wake_tx: Option<kanal::AsyncSender<()>>,
156 complete_blocks: Vec<u32>,
160 drain_ids: Vec<u32>,
164 highest_stream_id: u32,
166 closing: bool,
168 graceful: bool,
172 graceful_last_stream: u32,
175 shutdown: Option<CancellationToken>,
177 date_cache: Arc<DateCache>,
180}
181
182impl<Io> Connection<Io>
183where
184 Io: tokio::io::AsyncRead + tokio::io::AsyncWrite + Unpin,
185{
186 #[inline]
188 pub fn new(io: Io, preface_timeout: Option<Duration>) -> Connection<Io> {
189 Connection {
190 io,
191 decoder: FrameDecoder::new(DEFAULT_MAX_FRAME_SIZE),
192 writer: FrameWriter::new(DEFAULT_MAX_FRAME_SIZE),
193 out: Vec::new(),
194 encoder: Encoder::new(4096),
195 request_decoder: HpackDecoder::new(4096),
196 peer: PeerSettings::default(),
197 local: PeerSettings::default(),
198 preface_timeout,
199 streams: FxHashMap::default(),
200 conn_window: DEFAULT_INITIAL_WINDOW_SIZE as i64,
201 closed_streams: FxHashSet::default(),
202 opts: ConnectionOptions::default(),
203 wake_tx: None,
204 complete_blocks: Vec::new(),
205 drain_ids: Vec::new(),
206 highest_stream_id: 0,
207 closing: false,
208 graceful: false,
209 graceful_last_stream: 0,
210 shutdown: None,
211 date_cache: Arc::new(DateCache::new()),
212 }
213 }
214
215 #[inline]
220 pub fn with_shutdown(mut self, token: CancellationToken) -> Self {
221 self.shutdown = Some(token);
222 self
223 }
224
225 #[inline]
233 pub async fn drive(self) -> std::io::Result<()> {
234 self.handle(
235 Arc::new(|_| std::future::pending::<Result<Response<Incoming>, std::io::Error>>()),
236 ConnectionOptions::default(),
237 )
238 .await
239 }
240
241 #[inline]
249 pub async fn handle<F, Fut, ResB, ResBE, ResE>(
250 mut self,
251 request_fn: Arc<F>,
252 options: ConnectionOptions,
253 ) -> std::io::Result<()>
254 where
255 F: Fn(Request<Incoming>) -> Fut + 'static,
256 Fut: Future<Output = Result<Response<ResB>, ResE>> + 'static,
257 ResB: Body<Data = Bytes, Error = ResBE> + Unpin + 'static,
258 ResBE: std::error::Error + 'static,
259 ResE: std::error::Error + 'static,
260 {
261 self.opts = options;
262 self.request_decoder
264 .set_max_header_list_size(self.opts.max_header_list_size as usize);
265 self.decoder
266 .set_max_frame_size(self.opts.max_frame_size as usize);
267 self.writer.max_frame_size = self.opts.max_frame_size as usize;
268 self.peer.max_frame_size = self.opts.max_frame_size as usize;
269 self.conn_window = self.opts.initial_connection_window_size as i64;
270 match self.read_preface().await? {
271 None => return Ok(()), Some(false) => {
273 self.goaway(Reason::ProtocolError, b"invalid connection preface");
276 self.flush().await?;
277 return Ok(());
278 }
279 Some(true) => {}
280 }
281
282 self.writer.write_settings(
286 &mut self.out,
287 &[
288 Setting {
289 id: 0x03,
290 value: self.opts.max_concurrent_streams,
291 },
292 Setting {
293 id: 0x04,
294 value: self.opts.initial_stream_window_size,
295 },
296 Setting {
297 id: 0x05,
298 value: self.opts.max_frame_size,
299 },
300 Setting {
301 id: 0x08,
302 value: if self.opts.enable_connect_protocol {
303 1
304 } else {
305 0
306 },
307 },
308 ],
309 );
310 self.flush().await?;
311
312 let (wake_tx, wake_rx) = kanal::bounded_async(1);
313 self.wake_tx = Some(wake_tx);
314
315 let mut buf = [0u8; 8192];
316 let mut peer_goaway = false;
317 while !peer_goaway && !(self.graceful && self.streams.is_empty()) {
318 let wake_recv = wake_rx.recv().fuse();
319 let read = tokio::io::AsyncReadExt::read(&mut self.io, &mut buf).fuse();
320 let shutdown_token = self.shutdown.clone();
324 let shutdown_fut: Pin<Box<dyn futures_util::future::FusedFuture<Output = ()> + Send>> =
325 match &shutdown_token {
326 Some(token) => Box::pin(token.cancelled().fuse()),
327 None => Box::pin(futures_util::future::pending().fuse()),
328 };
329 pin_mut!(wake_recv);
330 pin_mut!(read);
331 pin_mut!(shutdown_fut);
332 let mut idle: Pin<Box<dyn futures_util::future::FusedFuture<Output = ()>>> =
336 match self.opts.idle_timeout {
337 Some(d) => Box::pin(
338 vibeio::time::timeout(d, futures_util::future::pending::<()>())
339 .map(|_| ())
340 .fuse(),
341 ),
342 None => Box::pin(futures_util::future::pending::<()>().fuse()),
343 };
344 futures_util::select! {
345 n = read => {
346 let n = match n {
347 Ok(n) => n,
348 Err(e) if self.streams.is_empty()
349 && matches!(
350 e.kind(),
351 std::io::ErrorKind::BrokenPipe
352 | std::io::ErrorKind::ConnectionReset
353 | std::io::ErrorKind::ConnectionAborted
354 | std::io::ErrorKind::UnexpectedEof
355 ) => {
356 return Ok(())
358 }
359 Err(e) => Err(e)?
360 };
361 if n == 0 {
362 break; }
364 self.decoder.extend(&buf[..n]);
365 peer_goaway = self.process_frames(&request_fn).await?;
366 self.drain_outbound();
367 self.flush().await?;
368 }
369 _ = wake_recv => {
370 self.drain_outbound();
372 self.flush().await?;
373 }
374 _ = shutdown_fut => {
375 self.begin_graceful_shutdown();
376 self.flush().await?;
377 }
378 _ = idle => {
379 self.begin_graceful_shutdown();
382 self.flush().await?;
383 break;
384 }
385 }
386 }
387 if self.graceful {
388 self.finish_graceful_shutdown();
389 }
390 self.flush().await?;
391 Ok(())
392 }
393
394 #[inline]
401 async fn read_preface(&mut self) -> std::io::Result<Option<bool>> {
402 let mut magic = [0u8; CLIENT_PREFACE.len()];
403 match self.preface_timeout {
404 Some(timeout) => {
405 match vibeio::time::timeout(
406 timeout,
407 tokio::io::AsyncReadExt::read_exact(&mut self.io, &mut magic),
408 )
409 .await
410 {
411 Ok(result) => {
412 result?;
413 }
414 Err(_elapsed) => return Ok(None),
415 }
416 }
417 None => {
418 tokio::io::AsyncReadExt::read_exact(&mut self.io, &mut magic).await?;
419 }
420 }
421 Ok(Some(magic == CLIENT_PREFACE))
422 }
423
424 #[inline]
431 async fn process_frames<F, Fut, ResB, ResBE, ResE>(
432 &mut self,
433 request_fn: &Arc<F>,
434 ) -> std::io::Result<bool>
435 where
436 F: Fn(Request<Incoming>) -> Fut + 'static,
437 Fut: Future<Output = Result<Response<ResB>, ResE>> + 'static,
438 ResB: Body<Data = Bytes, Error = ResBE> + Unpin + 'static,
439 ResBE: std::error::Error + 'static,
440 ResE: std::error::Error + 'static,
441 {
442 loop {
443 let frame = match self.decoder.next_frame() {
444 Ok(Some(frame)) => frame,
445 Ok(None) => return Ok(false),
446 Err(error) => {
447 self.goaway(error.reason, b"frame error");
451 self.flush().await?;
452 return Ok(true);
453 }
454 };
455 match frame {
456 Frame::Settings {
457 ack: false,
458 settings,
459 } => {
460 self.apply_peer_settings(&settings);
461 self.writer.write_settings_ack(&mut self.out);
462 }
463 Frame::Settings { ack: true, .. } => {}
464 Frame::Ping {
465 ack: false,
466 payload,
467 } => {
468 self.writer.write_ping_ack(&mut self.out, &payload);
469 }
470 Frame::Ping { ack: true, .. } => {}
471 Frame::GoAway { .. } => return Ok(true),
472 Frame::Headers {
473 stream_id,
474 end_stream,
475 end_headers,
476 block,
477 ..
478 } => {
479 self.handle_headers_frame(stream_id, end_stream, end_headers, &block);
480 }
481 Frame::Continuation {
482 stream_id,
483 end_headers,
484 block,
485 } => {
486 self.handle_continuation(stream_id, end_headers, &block);
487 }
488 Frame::Data {
489 stream_id,
490 end_stream,
491 data,
492 } => {
493 self.handle_data_frame(stream_id, end_stream, data).await;
494 }
495 Frame::Reset {
496 stream_id,
497 error_code,
498 } => {
499 self.handle_reset_frame(stream_id, error_code);
500 }
501 Frame::Priority { .. } => {}
502 Frame::WindowUpdate {
503 stream_id,
504 increment,
505 } => self.handle_window_update(stream_id, increment),
506 Frame::PushPromise { .. } => {
507 self.goaway(Reason::ProtocolError, b"push promise to server");
508 }
509 Frame::Unknown { .. } => {}
510 }
511 if let Some(id) = self.take_complete_block() {
515 self.finalize_field_block(id, request_fn).await;
516 }
517 if self.closing {
518 self.flush().await?;
519 return Ok(true);
520 }
521 }
522 }
523}
524struct ConnBody {
527 inner: Pin<Box<dyn Body<Data = Bytes, Error = std::io::Error>>>,
528}
529
530impl ConnBody {
531 #[inline]
532 fn new<ResB, ResBE>(body: ResB) -> Self
533 where
534 ResB: Body<Data = Bytes, Error = ResBE> + Unpin + 'static,
535 ResBE: std::error::Error + 'static,
536 {
537 ConnBody {
538 inner: Box::pin(BodyAdapter(Some(Box::pin(body)))),
539 }
540 }
541}
542
543impl Body for ConnBody {
544 type Data = Bytes;
545 type Error = std::io::Error;
546
547 #[inline]
548 fn poll_frame(
549 mut self: Pin<&mut Self>,
550 cx: &mut Context<'_>,
551 ) -> Poll<Option<Result<http_body::Frame<Self::Data>, Self::Error>>> {
552 self.inner.as_mut().poll_frame(cx)
553 }
554
555 #[inline]
556 fn size_hint(&self) -> http_body::SizeHint {
557 self.inner.size_hint()
558 }
559}
560
561#[inline]
566fn e2io<E: std::fmt::Display>(e: E) -> std::io::Error {
567 #[derive(Debug)]
568 struct Msg(String);
569 impl std::fmt::Display for Msg {
570 #[inline]
571 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
572 f.write_str(&self.0)
573 }
574 }
575 impl std::error::Error for Msg {}
576 std::io::Error::other(Msg(format!("{e}")))
577}
578
579struct BodyAdapter<ResB>(Option<Pin<Box<ResB>>>);
582
583impl<ResB, ResBE> Body for BodyAdapter<ResB>
584where
585 ResB: Body<Data = Bytes, Error = ResBE>,
586 ResBE: std::error::Error + 'static,
587{
588 type Data = Bytes;
589 type Error = std::io::Error;
590
591 #[inline]
592 fn poll_frame(
593 self: Pin<&mut Self>,
594 cx: &mut Context<'_>,
595 ) -> Poll<Option<Result<http_body::Frame<Self::Data>, Self::Error>>> {
596 let this = self.get_mut();
597 let Some(inner) = this.0.as_mut() else {
598 return Poll::Ready(None);
599 };
600 match inner.as_mut().poll_frame(cx) {
601 Poll::Ready(Some(Ok(frame))) => Poll::Ready(Some(Ok(frame))),
602 Poll::Ready(Some(Err(error))) => Poll::Ready(Some(Err(e2io(error)))),
603 Poll::Ready(None) => {
604 this.0 = None;
605 Poll::Ready(None)
606 }
607 Poll::Pending => Poll::Pending,
608 }
609 }
610
611 #[inline]
612 fn size_hint(&self) -> http_body::SizeHint {
613 match &self.0 {
614 Some(body) => body.size_hint(),
615 None => http_body::SizeHint::default(),
616 }
617 }
618}
619
620#[derive(Clone, Copy, Debug, PartialEq, Eq)]
621enum StreamDataState {
622 Idle,
623 Closed,
624 Bad,
625 Gone,
626 Ok,
627}
628
629mod handlers;
630
631#[cfg(test)]
632mod tests;