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 : #if defined(BOOST_MSVC)
28 : # pragma warning(push)
29 : # pragma warning(disable:4251)
30 : #endif
31 :
32 : namespace boost {
33 : namespace http_proto {
34 :
35 : class fields_base;
36 : struct header_limits;
37 :
38 : namespace detail {
39 :
40 : enum kind : unsigned char
41 : {
42 : fields = 0,
43 : request,
44 : response,
45 : };
46 :
47 : struct empty
48 : {
49 : kind param;
50 : };
51 :
52 :
53 : struct BOOST_HTTP_PROTO_DECL header
54 : {
55 : // +------------+---------+------+------------+-----------------------------+
56 : // | start-line | headers | \r\n | free space | entry[count-1] ... entry[0] |
57 : // +------------+---------+------+------------+-----------------------------+
58 : // ^ ^ ^ ^
59 : // buf buf+prefix buf+size buf+cap
60 :
61 : #ifdef BOOST_HTTP_PROTO_TEST_LIMITS
62 : using offset_type = std::uint8_t;
63 : #else
64 : using offset_type = std::uint32_t;
65 : #endif
66 :
67 : static constexpr
68 : std::size_t max_offset =
69 : std::numeric_limits<
70 : offset_type>::max();
71 :
72 : static constexpr
73 : field unknown_field =
74 : static_cast<field>(0);
75 :
76 : struct entry
77 : {
78 : offset_type np; // name pos
79 : offset_type nn; // name size
80 : offset_type vp; // value pos
81 : offset_type vn; // value size
82 : field id;
83 :
84 : entry operator+(
85 : std::size_t dv) const noexcept;
86 : entry operator-(
87 : std::size_t dv) const noexcept;
88 : };
89 :
90 : struct table
91 : {
92 : explicit
93 14080 : table(
94 : void* end) noexcept
95 14080 : : p_(reinterpret_cast<
96 : entry*>(end))
97 : {
98 14080 : }
99 :
100 : entry&
101 14195 : operator[](
102 : std::size_t i) const noexcept
103 : {
104 14195 : return p_[-1 * (
105 14195 : static_cast<
106 14195 : long>(i) + 1)];
107 : }
108 :
109 : private:
110 : entry* p_;
111 : };
112 :
113 : struct fld_t
114 : {
115 : };
116 :
117 : struct req_t
118 : {
119 : offset_type method_len;
120 : offset_type target_len;
121 : http_proto::method method;
122 : };
123 :
124 : struct res_t
125 : {
126 : unsigned short status_int;
127 : http_proto::status status;
128 : };
129 :
130 : //--------------------------------------------
131 :
132 : detail::kind kind;
133 : char const* cbuf = nullptr;
134 : char* buf = nullptr;
135 : std::size_t cap = 0;
136 :
137 : offset_type size = 0;
138 : offset_type count = 0;
139 : offset_type prefix = 0;
140 :
141 : http_proto::version version =
142 : http_proto::version::http_1_1;
143 : metadata md;
144 :
145 : union
146 : {
147 : fld_t fld;
148 : req_t req;
149 : res_t res;
150 : };
151 :
152 : private:
153 : struct fields_tag {};
154 : struct request_tag {};
155 : struct response_tag {};
156 :
157 : constexpr header(fields_tag) noexcept;
158 : constexpr header(request_tag) noexcept;
159 : constexpr header(response_tag) noexcept;
160 :
161 : public:
162 : // in fields_base.hpp
163 : static header&
164 : get(fields_base& f) noexcept;
165 :
166 : static header const*
167 : get_default(detail::kind k) noexcept;
168 :
169 : // called from parser
170 : explicit header(empty) noexcept;
171 :
172 : header(detail::kind) noexcept;
173 :
174 : void swap(header&) noexcept;
175 :
176 : bool keep_alive() const noexcept;
177 :
178 : static std::size_t bytes_needed(
179 : std::size_t size, std::size_t count) noexcept;
180 : static std::size_t table_space(
181 : std::size_t count) noexcept;
182 :
183 : std::size_t table_space() const noexcept;
184 :
185 : table tab() const noexcept;
186 : entry* tab_() const noexcept;
187 : bool is_default() const noexcept;
188 : std::size_t find(field) const noexcept;
189 : std::size_t find(core::string_view) const noexcept;
190 : void copy_table(void*, std::size_t) const noexcept;
191 : void copy_table(void*) const noexcept;
192 : void assign_to(header&) const noexcept;
193 :
194 : // metadata
195 :
196 : std::size_t maybe_count(field) const noexcept;
197 : bool is_special(field) const noexcept;
198 : void on_start_line();
199 : void on_insert(field, core::string_view);
200 : void on_erase(field);
201 : void on_insert_connection(core::string_view);
202 : void on_insert_content_length(core::string_view);
203 : void on_insert_expect(core::string_view);
204 : void on_insert_transfer_encoding(core::string_view);
205 : void on_insert_content_encoding(core::string_view);
206 : void on_insert_upgrade(core::string_view);
207 : void on_erase_connection();
208 : void on_erase_content_length();
209 : void on_erase_expect();
210 : void on_erase_transfer_encoding();
211 : void on_erase_content_encoding();
212 : void on_erase_upgrade();
213 : void on_erase_all(field);
214 : void update_payload() noexcept;
215 :
216 : // parsing
217 :
218 : static std::size_t
219 : count_crlf(core::string_view s) noexcept;
220 :
221 : void parse(
222 : std::size_t,
223 : header_limits const&,
224 : system::error_code&) noexcept;
225 : };
226 :
227 : #if defined(BOOST_MSVC)
228 : # pragma warning(pop)
229 : #endif
230 :
231 :
232 : } // detail
233 : } // http_proto
234 : } // boost
235 :
236 : #endif
|