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/align_up.hpp>
15 : #include <boost/http_proto/detail/config.hpp>
16 : #include <boost/http_proto/error.hpp>
17 : #include <boost/http_proto/field.hpp>
18 : #include <boost/http_proto/metadata.hpp>
19 : #include <boost/http_proto/method.hpp>
20 : #include <boost/http_proto/status.hpp>
21 : #include <boost/http_proto/version.hpp>
22 : #include <boost/core/detail/string_view.hpp>
23 : #include <boost/assert.hpp>
24 : #include <cstdint>
25 : #include <type_traits>
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 | free space | entry[count-1] ... entry[0] |
51 : // +------------+-----------+--------------+------------------------------+
52 : // ^ ^ ^ ^
53 : // buf buf+prefix buf+size buf+cap
54 :
55 : struct entry
56 : {
57 : offset_type np; // name pos
58 : offset_type nn; // name size
59 : offset_type vp; // value pos
60 : offset_type vn; // value size
61 : field id;
62 :
63 : entry operator+(
64 : std::size_t dv) const noexcept;
65 : entry operator-(
66 : std::size_t dv) const noexcept;
67 : };
68 :
69 : // HTTP-message = start-line CRLF *( field-line CRLF ) CRLF
70 : // start-line = request-line / status-line
71 : // status-line = HTTP-version SP status-code SP [ reason-phrase ]
72 : // status-code = 3DIGIT
73 : // HTTP-name = %x48.54.54.50 ; HTTP
74 : // HTTP-version = HTTP-name "/" DIGIT "." DIGIT
75 : //
76 : // => "HTTP/1.1 111 \r\n" + trailing "\r\n"
77 : static
78 : constexpr
79 : std::size_t const min_status_line = 17;
80 :
81 : // "X:\r\n"
82 : static
83 : constexpr
84 : std::size_t const min_field_line = 4;
85 :
86 : static
87 : constexpr
88 : std::size_t const max_field_lines =
89 : (max_offset - min_status_line) / min_field_line;
90 :
91 : /** Returns the largest permissible capacity in bytes
92 : */
93 : static
94 : constexpr
95 : std::size_t
96 11974 : max_capacity_in_bytes() noexcept
97 : {
98 : // the entire serialized contents of the header
99 : // must fit entirely in max_offset
100 11974 : return align_up(
101 : (max_offset + (max_field_lines * sizeof(entry))),
102 11974 : alignof(entry));
103 : }
104 :
105 : struct table
106 : {
107 : explicit
108 26882 : table(
109 : void* end) noexcept
110 26882 : : p_(reinterpret_cast<
111 : entry*>(end))
112 : {
113 26882 : }
114 :
115 : entry&
116 26918 : operator[](
117 : std::size_t i) const noexcept
118 : {
119 26918 : return p_[-1 * (
120 26918 : static_cast<
121 26918 : long>(i) + 1)];
122 : }
123 :
124 : private:
125 : entry* p_;
126 : };
127 :
128 : struct fld_t
129 : {
130 : };
131 :
132 : struct req_t
133 : {
134 : offset_type method_len;
135 : offset_type target_len;
136 : http_proto::method method;
137 : };
138 :
139 : struct res_t
140 : {
141 : unsigned short status_int;
142 : http_proto::status status;
143 : };
144 :
145 : //--------------------------------------------
146 :
147 : detail::kind kind;
148 : char const* cbuf = nullptr;
149 : char* buf = nullptr;
150 : std::size_t cap = 0;
151 : std::size_t max_cap = max_capacity_in_bytes();
152 :
153 : offset_type size = 0;
154 : offset_type count = 0;
155 : offset_type prefix = 0;
156 :
157 : http_proto::version version =
158 : http_proto::version::http_1_1;
159 : metadata md;
160 :
161 : union
162 : {
163 : fld_t fld;
164 : req_t req;
165 : res_t res;
166 : };
167 :
168 : private:
169 : struct fields_tag {};
170 : struct request_tag {};
171 : struct response_tag {};
172 :
173 : constexpr header(fields_tag) noexcept;
174 : constexpr header(request_tag) noexcept;
175 : constexpr header(response_tag) noexcept;
176 :
177 : public:
178 : // in fields_base.hpp
179 : static header& get(fields_base& f) noexcept;
180 :
181 : BOOST_HTTP_PROTO_DECL static header const*
182 : get_default(detail::kind k) noexcept;
183 :
184 : // called from parser
185 : explicit header(empty) noexcept;
186 :
187 : BOOST_HTTP_PROTO_DECL header(detail::kind) noexcept;
188 : BOOST_HTTP_PROTO_DECL void swap(header&) noexcept;
189 : BOOST_HTTP_PROTO_DECL bool keep_alive() const noexcept;
190 :
191 : static std::size_t bytes_needed(
192 : std::size_t size, std::size_t count) noexcept;
193 : static std::size_t table_space(
194 : std::size_t count) noexcept;
195 : std::size_t table_space() const noexcept;
196 :
197 : table tab() const noexcept;
198 : entry* tab_() const noexcept;
199 : bool is_default() const noexcept;
200 : std::size_t find(field) const noexcept;
201 : std::size_t find(core::string_view) const noexcept;
202 : void copy_table(void*, std::size_t) const noexcept;
203 : void copy_table(void*) const noexcept;
204 : void assign_to(header&) const noexcept;
205 :
206 : // metadata
207 :
208 : std::size_t maybe_count(field) const noexcept;
209 : bool is_special(field) const noexcept;
210 : void on_start_line();
211 : void on_insert(field, core::string_view);
212 : void on_erase(field);
213 : void on_insert_connection(core::string_view);
214 : void on_insert_content_length(core::string_view);
215 : void on_insert_expect(core::string_view);
216 : void on_insert_transfer_encoding();
217 : void on_insert_content_encoding(core::string_view);
218 : void on_insert_upgrade(core::string_view);
219 : void on_erase_connection();
220 : void on_erase_content_length();
221 : void on_erase_expect();
222 : void on_erase_transfer_encoding();
223 : void on_erase_content_encoding();
224 : void on_erase_upgrade();
225 : void on_erase_all(field);
226 : void update_payload() noexcept;
227 :
228 : // parsing
229 :
230 : static std::size_t count_crlf(
231 : core::string_view s) noexcept;
232 : BOOST_HTTP_PROTO_DECL void parse(
233 : std::size_t, header_limits const&,
234 : system::error_code&) noexcept;
235 : };
236 :
237 : } // detail
238 : } // http_proto
239 : } // boost
240 :
241 : #endif
|