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 3338 : max_capacity_in_bytes() noexcept 94 : { 95 : // the entire serialized contents of the header 96 : // must fit entirely in max_offset 97 3338 : return align_up( 98 : (max_offset + (max_field_lines * sizeof(entry))), 99 3338 : alignof(entry)); 100 : } 101 : 102 : struct table 103 : { 104 : explicit 105 5210 : table( 106 : void* end) noexcept 107 5210 : : p_(reinterpret_cast< 108 5210 : entry*>(end)) 109 : { 110 5210 : } 111 : 112 : entry& 113 5240 : operator[]( 114 : std::size_t i) const noexcept 115 : { 116 5240 : return p_[-1 * ( 117 5240 : static_cast< 118 5240 : 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