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