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