Line data Source code
1 : //
2 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 : // Copyright (c) 2024 Mohammad Nejati
4 : //
5 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 : //
8 : // Official repository: https://github.com/cppalliance/http_proto
9 : //
10 :
11 : #ifndef BOOST_HTTP_PROTO_DETAIL_HEADER_HPP
12 : #define BOOST_HTTP_PROTO_DETAIL_HEADER_HPP
13 :
14 : #include <boost/http_proto/detail/config.hpp>
15 : #include <boost/http_proto/error.hpp>
16 : #include <boost/http_proto/field.hpp>
17 : #include <boost/http_proto/metadata.hpp>
18 : #include <boost/http_proto/method.hpp>
19 : #include <boost/http_proto/status.hpp>
20 : #include <boost/http_proto/version.hpp>
21 :
22 : #include <boost/assert.hpp>
23 : #include <boost/core/detail/string_view.hpp>
24 :
25 : #include <cstdint>
26 :
27 : namespace boost {
28 : namespace http_proto {
29 :
30 : class fields_base;
31 : struct header_limits;
32 :
33 : namespace detail {
34 :
35 : enum kind : unsigned char
36 : {
37 : fields = 0,
38 : request,
39 : response,
40 : };
41 :
42 : struct empty
43 : {
44 : kind param;
45 : };
46 :
47 : struct header
48 : {
49 : // +------------+---------+------+------------+-----------------------------+
50 : // | start-line | headers | \r\n | free space | entry[count-1] ... entry[0] |
51 : // +------------+---------+------+------------+-----------------------------+
52 : // ^ ^ ^ ^
53 : // buf buf+prefix buf+size buf+cap
54 :
55 : #ifdef BOOST_HTTP_PROTO_TEST_LIMITS
56 : using offset_type = std::uint8_t;
57 : #else
58 : using offset_type = std::uint32_t;
59 : #endif
60 :
61 : static constexpr
62 : std::size_t max_offset =
63 : std::numeric_limits<
64 : offset_type>::max();
65 :
66 : static constexpr
67 : field unknown_field =
68 : static_cast<field>(0);
69 :
70 : struct entry
71 : {
72 : offset_type np; // name pos
73 : offset_type nn; // name size
74 : offset_type vp; // value pos
75 : offset_type vn; // value size
76 : field id;
77 :
78 : entry operator+(
79 : std::size_t dv) const noexcept;
80 : entry operator-(
81 : std::size_t dv) const noexcept;
82 : };
83 :
84 : struct table
85 : {
86 : explicit
87 14621 : table(
88 : void* end) noexcept
89 14621 : : p_(reinterpret_cast<
90 : entry*>(end))
91 : {
92 14621 : }
93 :
94 : entry&
95 14742 : operator[](
96 : std::size_t i) const noexcept
97 : {
98 14742 : return p_[-1 * (
99 14742 : static_cast<
100 14742 : long>(i) + 1)];
101 : }
102 :
103 : private:
104 : entry* p_;
105 : };
106 :
107 : struct fld_t
108 : {
109 : };
110 :
111 : struct req_t
112 : {
113 : offset_type method_len;
114 : offset_type target_len;
115 : http_proto::method method;
116 : };
117 :
118 : struct res_t
119 : {
120 : unsigned short status_int;
121 : http_proto::status status;
122 : };
123 :
124 : //--------------------------------------------
125 :
126 : detail::kind kind;
127 : char const* cbuf = nullptr;
128 : char* buf = nullptr;
129 : std::size_t cap = 0;
130 :
131 : offset_type size = 0;
132 : offset_type count = 0;
133 : offset_type prefix = 0;
134 :
135 : http_proto::version version =
136 : http_proto::version::http_1_1;
137 : metadata md;
138 :
139 : union
140 : {
141 : fld_t fld;
142 : req_t req;
143 : res_t res;
144 : };
145 :
146 : private:
147 : struct fields_tag {};
148 : struct request_tag {};
149 : struct response_tag {};
150 :
151 : constexpr header(fields_tag) noexcept;
152 : constexpr header(request_tag) noexcept;
153 : constexpr header(response_tag) noexcept;
154 :
155 : public:
156 : // in fields_base.hpp
157 : static header&
158 : get(fields_base& f) noexcept;
159 :
160 : BOOST_HTTP_PROTO_DECL
161 : static header const*
162 : get_default(detail::kind k) noexcept;
163 :
164 : // called from parser
165 : explicit header(empty) noexcept;
166 :
167 : BOOST_HTTP_PROTO_DECL
168 : header(detail::kind) noexcept;
169 :
170 : BOOST_HTTP_PROTO_DECL
171 : void swap(header&) noexcept;
172 :
173 : BOOST_HTTP_PROTO_DECL
174 : bool keep_alive() const noexcept;
175 :
176 : static std::size_t bytes_needed(
177 : std::size_t size, std::size_t count) noexcept;
178 : static std::size_t table_space(
179 : std::size_t count) noexcept;
180 :
181 : std::size_t table_space() const noexcept;
182 :
183 : table tab() const noexcept;
184 : entry* tab_() const noexcept;
185 : bool is_default() const noexcept;
186 : std::size_t find(field) const noexcept;
187 : std::size_t find(core::string_view) const noexcept;
188 : void copy_table(void*, std::size_t) const noexcept;
189 : void copy_table(void*) const noexcept;
190 : void assign_to(header&) const noexcept;
191 :
192 : // metadata
193 :
194 : std::size_t maybe_count(field) const noexcept;
195 : bool is_special(field) const noexcept;
196 : void on_start_line();
197 : void on_insert(field, core::string_view);
198 : void on_erase(field);
199 : void on_insert_connection(core::string_view);
200 : void on_insert_content_length(core::string_view);
201 : void on_insert_expect(core::string_view);
202 : void on_insert_transfer_encoding(core::string_view);
203 : void on_insert_content_encoding(core::string_view);
204 : void on_insert_upgrade(core::string_view);
205 : void on_erase_connection();
206 : void on_erase_content_length();
207 : void on_erase_expect();
208 : void on_erase_transfer_encoding();
209 : void on_erase_content_encoding();
210 : void on_erase_upgrade();
211 : void on_erase_all(field);
212 : void update_payload() noexcept;
213 :
214 : // parsing
215 :
216 : static std::size_t
217 : count_crlf(core::string_view s) noexcept;
218 :
219 : void parse(
220 : std::size_t,
221 : header_limits const&,
222 : system::error_code&) noexcept;
223 : };
224 :
225 : } // detail
226 : } // http_proto
227 : } // boost
228 :
229 : #endif
|