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