1#[cfg(all(feature = "server", feature = "runtime"))]
2use std::{pin::Pin, time::Duration};
3
4use bytes::BytesMut;
5use http::{HeaderMap, Method};
6use httparse::ParserConfig;
7#[cfg(all(feature = "server", feature = "runtime"))]
8use tokio::time::Sleep;
9
10use crate::body::DecodedLength;
11use crate::proto::{BodyLength, MessageHead};
12
13pub(crate) use self::conn::Conn;
14pub(crate) use self::decode::Decoder;
15pub(crate) use self::dispatch::Dispatcher;
16pub(crate) use self::encode::{EncodedBuf, Encoder};
17//TODO: move out of h1::io
18pub(crate) use self::io::MINIMUM_MAX_BUFFER_SIZE;
19
20mod conn;
21mod decode;
22pub(crate) mod dispatch;
23mod encode;
24mod io;
25mod role;
26
27cfg_client! {
28 pub(crate) type ClientTransaction = role::Client;
29}
30
31cfg_server! {
32 pub(crate) type ServerTransaction = role::Server;
33}
34
35pub(crate) trait Http1Transaction {
36 type Incoming;
37 type Outgoing: Default;
38 const LOG: &'static str;
39 fn parse(bytes: &mut BytesMut, ctx: ParseContext<'_>) -> ParseResult<Self::Incoming>;
40 fn encode(enc: Encode<'_, Self::Outgoing>, dst: &mut Vec<u8>) -> crate::Result<Encoder>;
41
42 fn on_error(err: &crate::Error) -> Option<MessageHead<Self::Outgoing>>;
43
44 fn is_client() -> bool {
45 !Self::is_server()
46 }
47
48 fn is_server() -> bool {
49 !Self::is_client()
50 }
51
52 fn should_error_on_parse_eof() -> bool {
53 Self::is_client()
54 }
55
56 fn should_read_first() -> bool {
57 Self::is_server()
58 }
59
60 fn update_date() {}
61}
62
63/// Result newtype for Http1Transaction::parse.
64pub(crate) type ParseResult<T> = Result<Option<ParsedMessage<T>>, crate::error::Parse>;
65
66#[derive(Debug)]
67pub(crate) struct ParsedMessage<T> {
68 head: MessageHead<T>,
69 decode: DecodedLength,
70 expect_continue: bool,
71 keep_alive: bool,
72 wants_upgrade: bool,
73}
74
75pub(crate) struct ParseContext<'a> {
76 cached_headers: &'a mut Option<HeaderMap>,
77 req_method: &'a mut Option<Method>,
78 h1_parser_config: ParserConfig,
79 #[cfg(all(feature = "server", feature = "runtime"))]
80 h1_header_read_timeout: Option<Duration>,
81 #[cfg(all(feature = "server", feature = "runtime"))]
82 h1_header_read_timeout_fut: &'a mut Option<Pin<Box<Sleep>>>,
83 #[cfg(all(feature = "server", feature = "runtime"))]
84 h1_header_read_timeout_running: &'a mut bool,
85 preserve_header_case: bool,
86 #[cfg(feature = "ffi")]
87 preserve_header_order: bool,
88 h09_responses: bool,
89 #[cfg(feature = "ffi")]
90 on_informational: &'a mut Option<crate::ffi::OnInformational>,
91 #[cfg(feature = "ffi")]
92 raw_headers: bool,
93}
94
95/// Passed to Http1Transaction::encode
96pub(crate) struct Encode<'a, T> {
97 head: &'a mut MessageHead<T>,
98 body: Option<BodyLength>,
99 #[cfg(feature = "server")]
100 keep_alive: bool,
101 req_method: &'a mut Option<Method>,
102 title_case_headers: bool,
103}
104
105/// Extra flags that a request "wants", like expect-continue or upgrades.
106#[derive(Clone, Copy, Debug)]
107struct Wants(u8);
108
109impl Wants {
110 const EMPTY: Wants = Wants(0b00);
111 const EXPECT: Wants = Wants(0b01);
112 const UPGRADE: Wants = Wants(0b10);
113
114 #[must_use]
115 fn add(self, other: Wants) -> Wants {
116 Wants(self.0 | other.0)
117 }
118
119 fn contains(&self, other: Wants) -> bool {
120 (self.0 & other.0) == other.0
121 }
122}
123