summaryrefslogtreecommitdiffstats
path: root/third_party/rust/neqo-http3/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/neqo-http3/src/lib.rs')
-rw-r--r--third_party/rust/neqo-http3/src/lib.rs290
1 files changed, 290 insertions, 0 deletions
diff --git a/third_party/rust/neqo-http3/src/lib.rs b/third_party/rust/neqo-http3/src/lib.rs
new file mode 100644
index 0000000000..4d9d3c6dff
--- /dev/null
+++ b/third_party/rust/neqo-http3/src/lib.rs
@@ -0,0 +1,290 @@
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![cfg_attr(feature = "deny-warnings", deny(warnings))]
+#![warn(clippy::pedantic)]
+#![allow(clippy::pub_enum_variant_names)]
+
+mod client_events;
+mod connection;
+pub mod connection_client;
+mod connection_server;
+mod control_stream_local;
+mod control_stream_remote;
+pub mod hframe;
+mod push_controller;
+mod push_stream;
+mod qlog;
+mod recv_message;
+mod send_message;
+pub mod server;
+mod server_connection_events;
+mod server_events;
+mod settings;
+mod stream_type_reader;
+
+use neqo_qpack::decoder::QPackDecoder;
+use neqo_qpack::Error as QpackError;
+pub use neqo_transport::Output;
+use neqo_transport::{AppError, Connection, Error as TransportError};
+use std::fmt::Debug;
+
+pub use client_events::Http3ClientEvent;
+pub use connection::Http3State;
+pub use connection_client::Http3Client;
+pub use connection_client::Http3Parameters;
+pub use hframe::HFrameReader;
+pub use neqo_qpack::Header;
+pub use server::Http3Server;
+pub use server_events::Http3ServerEvent;
+
+type Res<T> = Result<T, Error>;
+
+#[derive(Clone, Debug, PartialEq)]
+pub enum Error {
+ HttpNoError,
+ HttpGeneralProtocol,
+ HttpGeneralProtocolStream, //this is the same as the above but it should only close a stream not a connection.
+ HttpInternal,
+ HttpStreamCreation,
+ HttpClosedCriticalStream,
+ HttpFrameUnexpected,
+ HttpFrame,
+ HttpExcessiveLoad,
+ HttpId,
+ HttpSettings,
+ HttpMissingSettings,
+ HttpRequestRejected,
+ HttpRequestCancelled,
+ HttpRequestIncomplete,
+ HttpConnect,
+ HttpVersionFallback,
+ QpackError(neqo_qpack::Error),
+
+ // Internal errors from here.
+ AlreadyClosed,
+ AlreadyInitialized,
+ DecodingFrame,
+ HttpGoaway,
+ Internal,
+ InvalidResumptionToken,
+ InvalidStreamId,
+ InvalidState,
+ NoMoreData,
+ NotEnoughData,
+ TransportError(TransportError),
+ Unavailable,
+ Unexpected,
+ StreamLimitError,
+ TransportStreamDoesNotExist,
+ InvalidInput,
+ FatalError,
+ InvalidHeader,
+}
+
+impl Error {
+ #[must_use]
+ pub fn code(&self) -> AppError {
+ match self {
+ Self::HttpNoError => 0x100,
+ Self::HttpGeneralProtocol | Self::HttpGeneralProtocolStream | Self::InvalidHeader => {
+ 0x101
+ }
+ Self::HttpInternal => 0x102,
+ Self::HttpStreamCreation => 0x103,
+ Self::HttpClosedCriticalStream => 0x104,
+ Self::HttpFrameUnexpected => 0x105,
+ Self::HttpFrame => 0x106,
+ Self::HttpExcessiveLoad => 0x107,
+ Self::HttpId => 0x108,
+ Self::HttpSettings => 0x109,
+ Self::HttpMissingSettings => 0x10a,
+ Self::HttpRequestRejected => 0x10b,
+ Self::HttpRequestCancelled => 0x10c,
+ Self::HttpRequestIncomplete => 0x10d,
+ Self::HttpConnect => 0x10f,
+ Self::HttpVersionFallback => 0x110,
+ Self::QpackError(e) => e.code(),
+ // These are all internal errors.
+ _ => 3,
+ }
+ }
+
+ #[must_use]
+ pub fn connection_error(&self) -> bool {
+ matches!(
+ self,
+ Self::HttpGeneralProtocol
+ | Self::HttpInternal
+ | Self::HttpStreamCreation
+ | Self::HttpClosedCriticalStream
+ | Self::HttpFrameUnexpected
+ | Self::HttpFrame
+ | Self::HttpExcessiveLoad
+ | Self::HttpId
+ | Self::HttpSettings
+ | Self::HttpMissingSettings
+ | Self::QpackError(QpackError::EncoderStream)
+ | Self::QpackError(QpackError::DecoderStream)
+ )
+ }
+
+ #[must_use]
+ pub fn stream_reset_error(&self) -> bool {
+ matches!(self, Self::HttpGeneralProtocolStream | Self::InvalidHeader)
+ }
+
+ #[must_use]
+ pub fn map_stream_send_errors(err: &TransportError) -> Self {
+ match err {
+ TransportError::InvalidStreamId | TransportError::FinalSizeError => {
+ Error::TransportStreamDoesNotExist
+ }
+ TransportError::InvalidInput => Error::InvalidInput,
+ _ => {
+ debug_assert!(false, "Unexpected error");
+ Error::TransportStreamDoesNotExist
+ }
+ }
+ }
+
+ #[must_use]
+ pub fn map_stream_create_errors(err: &TransportError) -> Self {
+ match err {
+ TransportError::ConnectionState => Error::Unavailable,
+ TransportError::StreamLimitError => Error::StreamLimitError,
+ _ => {
+ debug_assert!(false, "Unexpected error");
+ Error::TransportStreamDoesNotExist
+ }
+ }
+ }
+
+ #[must_use]
+ pub fn map_stream_recv_errors(err: &TransportError) -> Self {
+ match err {
+ TransportError::NoMoreData => {
+ debug_assert!(
+ false,
+ "Do not call stream_recv if FIN has been previously read"
+ );
+ }
+ TransportError::InvalidStreamId => {}
+ _ => {
+ debug_assert!(false, "Unexpected error");
+ }
+ };
+ Error::TransportStreamDoesNotExist
+ }
+
+ #[must_use]
+ pub fn map_set_resumption_errors(err: &TransportError) -> Self {
+ match err {
+ TransportError::ConnectionState => Error::InvalidState,
+ _ => Error::InvalidResumptionToken,
+ }
+ }
+
+ /// # Errors
+ /// Any error is mapped to the indicated type.
+ fn map_error<R>(r: Result<R, impl Into<Self>>, err: Self) -> Result<R, Self> {
+ Ok(r.map_err(|e| {
+ debug_assert!(!matches!(e.into(), Self::HttpInternal));
+ debug_assert!(!matches!(err, Self::HttpInternal));
+ err
+ })?)
+ }
+}
+
+impl From<TransportError> for Error {
+ fn from(err: TransportError) -> Self {
+ Self::TransportError(err)
+ }
+}
+
+impl From<QpackError> for Error {
+ fn from(err: QpackError) -> Self {
+ match err {
+ QpackError::ClosedCriticalStream => Error::HttpClosedCriticalStream,
+ QpackError::InternalError => Error::HttpInternal,
+ e => Self::QpackError(e),
+ }
+ }
+}
+
+impl From<AppError> for Error {
+ fn from(error: AppError) -> Self {
+ match error {
+ 0x100 => Self::HttpNoError,
+ 0x101 => Self::HttpGeneralProtocol,
+ 0x103 => Self::HttpStreamCreation,
+ 0x104 => Self::HttpClosedCriticalStream,
+ 0x105 => Self::HttpFrameUnexpected,
+ 0x106 => Self::HttpFrame,
+ 0x107 => Self::HttpExcessiveLoad,
+ 0x108 => Self::HttpId,
+ 0x109 => Self::HttpSettings,
+ 0x10a => Self::HttpMissingSettings,
+ 0x10b => Self::HttpRequestRejected,
+ 0x10c => Self::HttpRequestCancelled,
+ 0x10d => Self::HttpRequestIncomplete,
+ 0x10f => Self::HttpConnect,
+ 0x110 => Self::HttpVersionFallback,
+ 0x200 => Self::QpackError(QpackError::DecompressionFailed),
+ 0x201 => Self::QpackError(QpackError::EncoderStream),
+ 0x202 => Self::QpackError(QpackError::DecoderStream),
+ _ => Self::HttpInternal,
+ }
+ }
+}
+
+impl ::std::error::Error for Error {
+ fn source(&self) -> Option<&(dyn ::std::error::Error + 'static)> {
+ match self {
+ Self::TransportError(e) => Some(e),
+ Self::QpackError(e) => Some(e),
+ _ => None,
+ }
+ }
+}
+
+impl ::std::fmt::Display for Error {
+ fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+ write!(f, "HTTP/3 error: {:?}", self)
+ }
+}
+
+pub trait RecvStream: Debug {
+ fn stream_reset(&self, error: AppError, decoder: &mut QPackDecoder, reset_type: ResetType);
+ /// # Errors
+ /// An error may happen while reading a stream, e.g. early close, protocol error, etc.
+ fn receive(&mut self, conn: &mut Connection, decoder: &mut QPackDecoder) -> Res<()>;
+ /// # Errors
+ /// An error may happen while reading a stream, e.g. early close, protocol error, etc.
+ fn header_unblocked(&mut self, conn: &mut Connection, decoder: &mut QPackDecoder) -> Res<()>;
+ fn done(&self) -> bool;
+ /// # Errors
+ /// An error may happen while reading a stream, e.g. early close, protocol error, etc.
+ fn read_data(
+ &mut self,
+ conn: &mut Connection,
+ decoder: &mut QPackDecoder,
+ buf: &mut [u8],
+ ) -> Res<(usize, bool)>;
+}
+
+pub(crate) trait RecvMessageEvents: Debug {
+ fn header_ready(&self, stream_id: u64, headers: Vec<Header>, interim: bool, fin: bool);
+ fn data_readable(&self, stream_id: u64);
+ fn reset(&self, stream_id: u64, error: AppError, local: bool);
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum ResetType {
+ App,
+ Remote,
+ Local,
+}