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