92.67% Lines (569/614) 82.46% Functions (47/57)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) 2   // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3   // Copyright (c) 2024 Mohammad Nejati 3   // Copyright (c) 2024 Mohammad Nejati
4   // 4   //
5   // Distributed under the Boost Software License, Version 1.0. (See accompanying 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) 6   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7   // 7   //
8   // Official repository: https://github.com/cppalliance/http 8   // Official repository: https://github.com/cppalliance/http
9   // 9   //
10   10  
11   #include "src/rfc/detail/rules.hpp" 11   #include "src/rfc/detail/rules.hpp"
12   #include "src/rfc/detail/transfer_coding_rule.hpp" 12   #include "src/rfc/detail/transfer_coding_rule.hpp"
13   13  
14   #include <boost/http/detail/header.hpp> 14   #include <boost/http/detail/header.hpp>
15   #include <boost/http/field.hpp> 15   #include <boost/http/field.hpp>
16   #include <boost/http/header_limits.hpp> 16   #include <boost/http/header_limits.hpp>
17   #include <boost/http/rfc/list_rule.hpp> 17   #include <boost/http/rfc/list_rule.hpp>
18   #include <boost/http/rfc/token_rule.hpp> 18   #include <boost/http/rfc/token_rule.hpp>
19   #include <boost/http/rfc/upgrade_rule.hpp> 19   #include <boost/http/rfc/upgrade_rule.hpp>
20   #include <boost/assert.hpp> 20   #include <boost/assert.hpp>
21   #include <boost/assert/source_location.hpp> 21   #include <boost/assert/source_location.hpp>
22   #include <boost/static_assert.hpp> 22   #include <boost/static_assert.hpp>
23   #include <boost/url/grammar/ci_string.hpp> 23   #include <boost/url/grammar/ci_string.hpp>
24   #include <boost/url/grammar/parse.hpp> 24   #include <boost/url/grammar/parse.hpp>
25   #include <boost/url/grammar/range_rule.hpp> 25   #include <boost/url/grammar/range_rule.hpp>
26   #include <boost/url/grammar/recycled.hpp> 26   #include <boost/url/grammar/recycled.hpp>
27   #include <boost/url/grammar/unsigned_rule.hpp> 27   #include <boost/url/grammar/unsigned_rule.hpp>
28   28  
29   #include <utility> 29   #include <utility>
30   30  
31   namespace boost { 31   namespace boost {
32   namespace http { 32   namespace http {
33   namespace detail { 33   namespace detail {
34   34  
35   //------------------------------------------------ 35   //------------------------------------------------
36   36  
37   auto 37   auto
HITCBC 38   87 header:: 38   87 header::
39   entry:: 39   entry::
40   operator+( 40   operator+(
41   std::size_t dv) const noexcept -> 41   std::size_t dv) const noexcept ->
42   entry 42   entry
43   { 43   {
44   return { 44   return {
45   static_cast< 45   static_cast<
HITCBC 46   87 offset_type>(np + dv), 46   87 offset_type>(np + dv),
HITCBC 47   87 nn, 47   87 nn,
48   static_cast< 48   static_cast<
HITCBC 49   87 offset_type>(vp + dv), 49   87 offset_type>(vp + dv),
HITCBC 50   87 vn, 50   87 vn,
HITCBC 51   87 id }; 51   87 id };
52   } 52   }
53   53  
54   auto 54   auto
HITCBC 55   101 header:: 55   101 header::
56   entry:: 56   entry::
57   operator-( 57   operator-(
58   std::size_t dv) const noexcept -> 58   std::size_t dv) const noexcept ->
59   entry 59   entry
60   { 60   {
61   return { 61   return {
62   static_cast< 62   static_cast<
HITCBC 63   101 offset_type>(np - dv), 63   101 offset_type>(np - dv),
HITCBC 64   101 nn, 64   101 nn,
65   static_cast< 65   static_cast<
HITCBC 66   101 offset_type>(vp - dv), 66   101 offset_type>(vp - dv),
HITCBC 67   101 vn, 67   101 vn,
HITCBC 68   101 id }; 68   101 id };
69   } 69   }
70   70  
71   //------------------------------------------------ 71   //------------------------------------------------
72   72  
73   constexpr field header::unknown_field; 73   constexpr field header::unknown_field;
74   74  
75   //------------------------------------------------ 75   //------------------------------------------------
76   76  
  77 + constexpr
ECB 77   15 header:: 78   header::
ECB 78   15 header(fields_tag) noexcept 79   header(fields_tag) noexcept
ECB 79   15 : kind(detail::kind::fields) 80   : kind(detail::kind::fields)
ECB 80   15 , cbuf("\r\n") 81   , cbuf("\r\n")
ECB 81   15 , size(2) 82   , size(2)
ECB 82   15 , fld{} 83   , fld{}
83   { 84   {
ECB 84   15 } 85   }
85   86  
  87 + constexpr
ECB 86   15 header:: 88   header::
ECB 87   15 header(request_tag) noexcept 89   header(request_tag) noexcept
ECB 88   15 : kind(detail::kind::request) 90   : kind(detail::kind::request)
ECB 89   15 , cbuf("GET / HTTP/1.1\r\n\r\n") 91   , cbuf("GET / HTTP/1.1\r\n\r\n")
ECB 90   15 , size(18) 92   , size(18)
ECB 91   15 , prefix(16) 93   , prefix(16)
ECB 92   15 , req{ 3, 1, 94   , req{ 3, 1,
ECB 93   15 http::method::get } 95   http::method::get }
94   { 96   {
ECB 95   15 } 97   }
96   98  
  99 + constexpr
ECB 97   15 header:: 100   header::
ECB 98   15 header(response_tag) noexcept 101   header(response_tag) noexcept
ECB 99   15 : kind(detail::kind::response) 102   : kind(detail::kind::response)
ECB 100   15 , cbuf("HTTP/1.1 200 OK\r\n\r\n") 103   , cbuf("HTTP/1.1 200 OK\r\n\r\n")
ECB 101   15 , size(19) 104   , size(19)
ECB 102   15 , prefix(17) 105   , prefix(17)
ECB 103   15 , res{ 200, 106   , res{ 200,
ECB 104   15 http::status::ok } 107   http::status::ok }
105   { 108   {
ECB 106   15 } 109   }
107   110  
108   //------------------------------------------------ 111   //------------------------------------------------
109   112  
110   header const* 113   header const*
HITCBC 111   4872 header:: 114   4872 header::
112   get_default(detail::kind k) noexcept 115   get_default(detail::kind k) noexcept
113   { 116   {
114 - static header const h[3] = { 117 + static constexpr header h[3] = {
115   fields_tag{}, 118   fields_tag{},
116   request_tag{}, 119   request_tag{},
ECB 117   4872 response_tag{}}; 120   response_tag{}};
HITCBC 118   4872 return &h[k]; 121   4872 return &h[k];
119   } 122   }
120   123  
HITCBC 121   13370 header:: 124   13370 header::
HITCBC 122   13370 header(empty v) noexcept 125   13370 header(empty v) noexcept
HITCBC 123   13370 : kind(v.param) 126   13370 : kind(v.param)
124   { 127   {
HITCBC 125   13370 } 128   13370 }
126   129  
HITCBC 127   2679 header:: 130   2679 header::
HITCBC 128   2679 header(detail::kind k) noexcept 131   2679 header(detail::kind k) noexcept
HITCBC 129   2679 : header(*get_default(k)) 132   2679 : header(*get_default(k))
130   { 133   {
HITCBC 131   2679 } 134   2679 }
132   135  
133   void 136   void
HITCBC 134   79 header:: 137   79 header::
135   swap(header& h) noexcept 138   swap(header& h) noexcept
136   { 139   {
HITCBC 137   79 std::swap(cbuf, h.cbuf); 140   79 std::swap(cbuf, h.cbuf);
HITCBC 138   79 std::swap(buf, h.buf); 141   79 std::swap(buf, h.buf);
HITCBC 139   79 std::swap(cap, h.cap); 142   79 std::swap(cap, h.cap);
HITCBC 140   79 std::swap(size, h.size); 143   79 std::swap(size, h.size);
HITCBC 141   79 std::swap(count, h.count); 144   79 std::swap(count, h.count);
HITCBC 142   79 std::swap(prefix, h.prefix); 145   79 std::swap(prefix, h.prefix);
HITCBC 143   79 std::swap(version, h.version); 146   79 std::swap(version, h.version);
HITCBC 144   79 std::swap(md, h.md); 147   79 std::swap(md, h.md);
HITCBC 145   79 switch(kind) 148   79 switch(kind)
146   { 149   {
HITCBC 147   15 default: 150   15 default:
148   case detail::kind::fields: 151   case detail::kind::fields:
HITCBC 149   15 break; 152   15 break;
HITCBC 150   56 case detail::kind::request: 153   56 case detail::kind::request:
HITCBC 151   56 std::swap( 154   56 std::swap(
HITCBC 152   56 req.method_len, h.req.method_len); 155   56 req.method_len, h.req.method_len);
HITCBC 153   56 std::swap( 156   56 std::swap(
HITCBC 154   56 req.target_len, h.req.target_len); 157   56 req.target_len, h.req.target_len);
HITCBC 155   56 std::swap(req.method, h.req.method); 158   56 std::swap(req.method, h.req.method);
HITCBC 156   56 break; 159   56 break;
HITCBC 157   8 case detail::kind::response: 160   8 case detail::kind::response:
HITCBC 158   8 std::swap( 161   8 std::swap(
HITCBC 159   8 res.status_int, h.res.status_int); 162   8 res.status_int, h.res.status_int);
HITCBC 160   8 std::swap(res.status, h.res.status); 163   8 std::swap(res.status, h.res.status);
HITCBC 161   8 break; 164   8 break;
162   } 165   }
HITCBC 163   79 } 166   79 }
164   167  
165   /* References: 168   /* References:
166   169  
167   6.3. Persistence 170   6.3. Persistence
168   https://datatracker.ietf.org/doc/html/rfc7230#section-6.3 171   https://datatracker.ietf.org/doc/html/rfc7230#section-6.3
169   */ 172   */
170   bool 173   bool
HITCBC 171   24 header:: 174   24 header::
172   keep_alive() const noexcept 175   keep_alive() const noexcept
173   { 176   {
HITCBC 174   24 if(md.payload == payload::error) 177   24 if(md.payload == payload::error)
HITCBC 175   1 return false; 178   1 return false;
HITCBC 176   23 if( version == 179   23 if( version ==
177   http::version::http_1_1) 180   http::version::http_1_1)
178   { 181   {
HITCBC 179   15 if(md.connection.close) 182   15 if(md.connection.close)
HITCBC 180   5 return false; 183   5 return false;
181   } 184   }
182   else 185   else
183   { 186   {
HITCBC 184   8 if(! md.connection.keep_alive) 187   8 if(! md.connection.keep_alive)
HITCBC 185   4 return false; 188   4 return false;
186   } 189   }
187   // can't use to_eof in requests 190   // can't use to_eof in requests
HITCBC 188   14 BOOST_ASSERT( 191   14 BOOST_ASSERT(
189   kind != detail::kind::request || 192   kind != detail::kind::request ||
190   md.payload != payload::to_eof); 193   md.payload != payload::to_eof);
HITCBC 191   14 if(md.payload == payload::to_eof) 194   14 if(md.payload == payload::to_eof)
HITCBC 192   3 return false; 195   3 return false;
HITCBC 193   11 return true; 196   11 return true;
194   } 197   }
195   198  
196   //------------------------------------------------ 199   //------------------------------------------------
197   200  
198   // return total bytes needed 201   // return total bytes needed
199   // to store message of `size` 202   // to store message of `size`
200   // bytes and `count` fields. 203   // bytes and `count` fields.
201   std::size_t 204   std::size_t
HITCBC 202   3156 header:: 205   3156 header::
203   bytes_needed( 206   bytes_needed(
204   std::size_t size, 207   std::size_t size,
205   std::size_t count) noexcept 208   std::size_t count) noexcept
206   { 209   {
207   // make sure `size` is big enough 210   // make sure `size` is big enough
208   // to hold the largest default buffer: 211   // to hold the largest default buffer:
209   // "HTTP/1.1 200 OK\r\n\r\n" 212   // "HTTP/1.1 200 OK\r\n\r\n"
HITCBC 210   3156 if(size < 19) 213   3156 if(size < 19)
HITCBC 211   2388 size = 19; 214   2388 size = 19;
212   215  
213   // align size up to alignof(entry) 216   // align size up to alignof(entry)
HITCBC 214   3156 size = (size + alignof(entry) - 1) & ~(alignof(entry) - 1); 217   3156 size = (size + alignof(entry) - 1) & ~(alignof(entry) - 1);
215   218  
HITCBC 216   3156 return size + count * sizeof(entry); 219   3156 return size + count * sizeof(entry);
217   } 220   }
218   221  
219   std::size_t 222   std::size_t
HITCBC 220   9585 header:: 223   9585 header::
221   table_space( 224   table_space(
222   std::size_t count) noexcept 225   std::size_t count) noexcept
223   { 226   {
224   return count * 227   return count *
HITCBC 225   9585 sizeof(header::entry); 228   9585 sizeof(header::entry);
226   } 229   }
227   230  
228   std::size_t 231   std::size_t
HITCBC 229   9585 header:: 232   9585 header::
230   table_space() const noexcept 233   table_space() const noexcept
231   { 234   {
HITCBC 232   9585 return table_space(count); 235   9585 return table_space(count);
233   } 236   }
234   237  
235   auto 238   auto
HITCBC 236   2669 header:: 239   2669 header::
237   tab() const noexcept -> 240   tab() const noexcept ->
238   table 241   table
239   { 242   {
HITCBC 240   2669 BOOST_ASSERT(cap > 0); 243   2669 BOOST_ASSERT(cap > 0);
HITCBC 241   2669 BOOST_ASSERT(buf != nullptr); 244   2669 BOOST_ASSERT(buf != nullptr);
HITCBC 242   2669 return table(buf + cap); 245   2669 return table(buf + cap);
243   } 246   }
244   247  
245   auto 248   auto
HITCBC 246   680 header:: 249   680 header::
247   tab_() const noexcept -> 250   tab_() const noexcept ->
248   entry* 251   entry*
249   { 252   {
250   return reinterpret_cast< 253   return reinterpret_cast<
HITCBC 251   680 entry*>(buf + cap); 254   680 entry*>(buf + cap);
252   } 255   }
253   256  
254   // return true if header cbuf is a default 257   // return true if header cbuf is a default
255   bool 258   bool
HITCBC 256   45 header:: 259   45 header::
257   is_default() const noexcept 260   is_default() const noexcept
258   { 261   {
HITCBC 259   45 return buf == nullptr; 262   45 return buf == nullptr;
260   } 263   }
261   264  
262   std::size_t 265   std::size_t
HITCBC 263   135 header:: 266   135 header::
264   find( 267   find(
265   field id) const noexcept 268   field id) const noexcept
266   { 269   {
HITCBC 267   135 if(count == 0) 270   135 if(count == 0)
HITCBC 268   64 return 0; 271   64 return 0;
HITCBC 269   71 std::size_t i = 0; 272   71 std::size_t i = 0;
HITCBC 270   71 auto const* p = &tab()[0]; 273   71 auto const* p = &tab()[0];
HITCBC 271   118 while(i < count) 274   118 while(i < count)
272   { 275   {
HITCBC 273   95 if(p->id == id) 276   95 if(p->id == id)
HITCBC 274   48 break; 277   48 break;
HITCBC 275   47 ++i; 278   47 ++i;
HITCBC 276   47 --p; 279   47 --p;
277   } 280   }
HITCBC 278   71 return i; 281   71 return i;
279   } 282   }
280   283  
281   std::size_t 284   std::size_t
HITCBC 282   42 header:: 285   42 header::
283   find( 286   find(
284   core::string_view name) const noexcept 287   core::string_view name) const noexcept
285   { 288   {
HITCBC 286   42 if(count == 0) 289   42 if(count == 0)
HITCBC 287   6 return 0; 290   6 return 0;
HITCBC 288   36 std::size_t i = 0; 291   36 std::size_t i = 0;
HITCBC 289   36 auto const* p = &tab()[0]; 292   36 auto const* p = &tab()[0];
HITCBC 290   57 while(i < count) 293   57 while(i < count)
291   { 294   {
292   core::string_view s( 295   core::string_view s(
HITCBC 293   54 cbuf + prefix + p->np, 296   54 cbuf + prefix + p->np,
HITCBC 294   54 p->nn); 297   54 p->nn);
HITCBC 295   54 if(grammar::ci_is_equal(s, name)) 298   54 if(grammar::ci_is_equal(s, name))
HITCBC 296   33 break; 299   33 break;
HITCBC 297   21 ++i; 300   21 ++i;
HITCBC 298   21 --p; 301   21 --p;
299   } 302   }
HITCBC 300   36 return i; 303   36 return i;
301   } 304   }
302   305  
303   void 306   void
HITCBC 304   2267 header:: 307   2267 header::
305   copy_table( 308   copy_table(
306   void* dest, 309   void* dest,
307   std::size_t n) const noexcept 310   std::size_t n) const noexcept
308   { 311   {
309   // When `n == 0`, cbuf + cap may have incorrect 312   // When `n == 0`, cbuf + cap may have incorrect
310   // alignment, which can trigger UB sanitizer. 313   // alignment, which can trigger UB sanitizer.
HITCBC 311   2267 if(n == 0) 314   2267 if(n == 0)
HITCBC 312   2246 return; 315   2246 return;
313   316  
HITCBC 314   21 std::memcpy( 317   21 std::memcpy(
315   reinterpret_cast< 318   reinterpret_cast<
HITCBC 316   21 entry*>(dest) - n, 319   21 entry*>(dest) - n,
317   reinterpret_cast< 320   reinterpret_cast<
318   entry const*>( 321   entry const*>(
HITCBC 319   21 cbuf + cap) - n, 322   21 cbuf + cap) - n,
320   n * sizeof(entry)); 323   n * sizeof(entry));
321   } 324   }
322   325  
323   void 326   void
HITCBC 324   2267 header:: 327   2267 header::
325   copy_table( 328   copy_table(
326   void* dest) const noexcept 329   void* dest) const noexcept
327   { 330   {
HITCBC 328   2267 copy_table(dest, count); 331   2267 copy_table(dest, count);
HITCBC 329   2267 } 332   2267 }
330   333  
331   // assign all the members but 334   // assign all the members but
332   // preserve the allocated memory 335   // preserve the allocated memory
333   void 336   void
HITCBC 334   2217 header:: 337   2217 header::
335   assign_to( 338   assign_to(
336   header& dest) const noexcept 339   header& dest) const noexcept
337   { 340   {
HITCBC 338   2217 auto const buf_ = dest.buf; 341   2217 auto const buf_ = dest.buf;
HITCBC 339   2217 auto const cbuf_ = dest.cbuf; 342   2217 auto const cbuf_ = dest.cbuf;
HITCBC 340   2217 auto const cap_ = dest.cap; 343   2217 auto const cap_ = dest.cap;
HITCBC 341   2217 dest = *this; 344   2217 dest = *this;
HITCBC 342   2217 dest.buf = buf_; 345   2217 dest.buf = buf_;
HITCBC 343   2217 dest.cbuf = cbuf_; 346   2217 dest.cbuf = cbuf_;
HITCBC 344   2217 dest.cap = cap_; 347   2217 dest.cap = cap_;
HITCBC 345   2217 } 348   2217 }
346   349  
347   //------------------------------------------------ 350   //------------------------------------------------
348   // 351   //
349   // Metadata 352   // Metadata
350   // 353   //
351   //------------------------------------------------ 354   //------------------------------------------------
352   355  
353   std::size_t 356   std::size_t
MISUBC 354   ✗ header:: 357   ✗ header::
355   maybe_count( 358   maybe_count(
356   field id) const noexcept 359   field id) const noexcept
357   { 360   {
MISUBC 358   ✗ if(kind == detail::kind::fields) 361   ✗ if(kind == detail::kind::fields)
MISUBC 359   ✗ return std::size_t(-1); 362   ✗ return std::size_t(-1);
MISUBC 360   ✗ switch(id) 363   ✗ switch(id)
361   { 364   {
MISUBC 362   ✗ case field::connection: 365   ✗ case field::connection:
MISUBC 363   ✗ return md.connection.count; 366   ✗ return md.connection.count;
MISUBC 364   ✗ case field::content_encoding: 367   ✗ case field::content_encoding:
MISUBC 365   ✗ return md.content_encoding.count; 368   ✗ return md.content_encoding.count;
MISUBC 366   ✗ case field::content_length: 369   ✗ case field::content_length:
MISUBC 367   ✗ return md.content_length.count; 370   ✗ return md.content_length.count;
MISUBC 368   ✗ case field::expect: 371   ✗ case field::expect:
MISUBC 369   ✗ return md.expect.count; 372   ✗ return md.expect.count;
MISUBC 370   ✗ case field::transfer_encoding: 373   ✗ case field::transfer_encoding:
MISUBC 371   ✗ return md.transfer_encoding.count; 374   ✗ return md.transfer_encoding.count;
MISUBC 372   ✗ case field::upgrade: 375   ✗ case field::upgrade:
MISUBC 373   ✗ return md.upgrade.count; 376   ✗ return md.upgrade.count;
MISUBC 374   ✗ default: 377   ✗ default:
MISUBC 375   ✗ break; 378   ✗ break;
376   } 379   }
MISUBC 377   ✗ return std::size_t(-1); 380   ✗ return std::size_t(-1);
378   } 381   }
379   382  
380   bool 383   bool
HITCBC 381   24 header:: 384   24 header::
382   is_special( 385   is_special(
383   field id) const noexcept 386   field id) const noexcept
384   { 387   {
HITCBC 385   24 if(kind == detail::kind::fields) 388   24 if(kind == detail::kind::fields)
HITCBC 386   5 return false; 389   5 return false;
HITCBC 387   19 switch(id) 390   19 switch(id)
388   { 391   {
HITCBC 389   9 case field::connection: 392   9 case field::connection:
390   case field::content_encoding: 393   case field::content_encoding:
391   case field::content_length: 394   case field::content_length:
392   case field::expect: 395   case field::expect:
393   case field::transfer_encoding: 396   case field::transfer_encoding:
394   case field::upgrade: 397   case field::upgrade:
HITCBC 395   9 return true; 398   9 return true;
HITCBC 396   10 default: 399   10 default:
HITCBC 397   10 break; 400   10 break;
398   } 401   }
HITCBC 399   10 return false; 402   10 return false;
400   } 403   }
401   404  
402   //------------------------------------------------ 405   //------------------------------------------------
403   406  
404   // called when the start-line changes 407   // called when the start-line changes
405   void 408   void
HITCBC 406   10668 header:: 409   10668 header::
407   on_start_line() 410   on_start_line()
408   { 411   {
409   // items in both the request-line 412   // items in both the request-line
410   // and the status-line can affect 413   // and the status-line can affect
411   // the payload, for example whether 414   // the payload, for example whether
412   // or not EOF marks the end of the 415   // or not EOF marks the end of the
413   // payload. 416   // payload.
414   417  
HITCBC 415   10668 update_payload(); 418   10668 update_payload();
HITCBC 416   10668 } 419   10668 }
417   420  
418   // called after a field is inserted 421   // called after a field is inserted
419   void 422   void
HITCBC 420   11031 header:: 423   11031 header::
421   on_insert( 424   on_insert(
422   field id, 425   field id,
423   core::string_view v) 426   core::string_view v)
424   { 427   {
HITCBC 425   11031 if(kind == detail::kind::fields) 428   11031 if(kind == detail::kind::fields)
HITCBC 426   482 return; 429   482 return;
HITCBC 427   10549 switch(id) 430   10549 switch(id)
428   { 431   {
HITCBC 429   7 case field::content_encoding: 432   7 case field::content_encoding:
HITCBC 430   7 return on_insert_content_encoding(v); 433   7 return on_insert_content_encoding(v);
HITCBC 431   4557 case field::content_length: 434   4557 case field::content_length:
HITCBC 432   4557 return on_insert_content_length(v); 435   4557 return on_insert_content_length(v);
HITCBC 433   141 case field::connection: 436   141 case field::connection:
HITCBC 434   141 return on_insert_connection(v); 437   141 return on_insert_connection(v);
HITCBC 435   47 case field::expect: 438   47 case field::expect:
HITCBC 436   47 return on_insert_expect(v); 439   47 return on_insert_expect(v);
HITCBC 437   4413 case field::transfer_encoding: 440   4413 case field::transfer_encoding:
HITCBC 438   4413 return on_insert_transfer_encoding(v); 441   4413 return on_insert_transfer_encoding(v);
HITCBC 439   24 case field::upgrade: 442   24 case field::upgrade:
HITCBC 440   24 return on_insert_upgrade(v); 443   24 return on_insert_upgrade(v);
HITCBC 441   1360 default: 444   1360 default:
HITCBC 442   1360 break; 445   1360 break;
443   } 446   }
444   } 447   }
445   448  
446   // called when one field is erased 449   // called when one field is erased
447   void 450   void
HITCBC 448   39 header:: 451   39 header::
449   on_erase(field id) 452   on_erase(field id)
450   { 453   {
HITCBC 451   39 if(kind == detail::kind::fields) 454   39 if(kind == detail::kind::fields)
HITCBC 452   3 return; 455   3 return;
HITCBC 453   36 switch(id) 456   36 switch(id)
454   { 457   {
HITCBC 455   9 case field::connection: 458   9 case field::connection:
HITCBC 456   9 return on_erase_connection(); 459   9 return on_erase_connection();
MISUBC 457   ✗ case field::content_encoding: 460   ✗ case field::content_encoding:
MISUBC 458   ✗ return on_erase_content_encoding(); 461   ✗ return on_erase_content_encoding();
HITCBC 459   4 case field::content_length: 462   4 case field::content_length:
HITCBC 460   4 return on_erase_content_length(); 463   4 return on_erase_content_length();
HITCBC 461   10 case field::expect: 464   10 case field::expect:
HITCBC 462   10 return on_erase_expect(); 465   10 return on_erase_expect();
HITCBC 463   4 case field::transfer_encoding: 466   4 case field::transfer_encoding:
HITCBC 464   4 return on_erase_transfer_encoding(); 467   4 return on_erase_transfer_encoding();
HITCBC 465   4 case field::upgrade: 468   4 case field::upgrade:
HITCBC 466   4 return on_erase_upgrade(); 469   4 return on_erase_upgrade();
HITCBC 467   5 default: 470   5 default:
HITCBC 468   5 break; 471   5 break;
469   } 472   }
470   } 473   }
471   474  
472   //------------------------------------------------ 475   //------------------------------------------------
473   476  
474   /* 477   /*
475   https://datatracker.ietf.org/doc/html/rfc7230#section-6.1 478   https://datatracker.ietf.org/doc/html/rfc7230#section-6.1
476   */ 479   */
477   void 480   void
HITCBC 478   148 header:: 481   148 header::
479   on_insert_connection( 482   on_insert_connection(
480   core::string_view v) 483   core::string_view v)
481   { 484   {
HITCBC 482   148 ++md.connection.count; 485   148 ++md.connection.count;
HITCBC 483   148 if(md.connection.ec) 486   148 if(md.connection.ec)
HITCBC 484   5 return; 487   5 return;
485   auto rv = grammar::parse( 488   auto rv = grammar::parse(
HITCBC 486   147 v, list_rule(token_rule, 1)); 489   147 v, list_rule(token_rule, 1));
HITCBC 487   147 if(! rv) 490   147 if(! rv)
488   { 491   {
HITCBC 489   4 md.connection.ec = 492   4 md.connection.ec =
HITGIC 490 - error::bad_connection; 493 + 8 BOOST_HTTP_ERR(
  494 + error::bad_connection);
HITCBC 491   4 return; 495   4 return;
492   } 496   }
HITCBC 493   143 md.connection.ec = {}; 497   143 md.connection.ec = {};
HITCBC 494   297 for(auto t : *rv) 498   297 for(auto t : *rv)
495   { 499   {
HITCBC 496   154 if(grammar::ci_is_equal( 500   154 if(grammar::ci_is_equal(
497   t, "close")) 501   t, "close"))
HITCBC 498   99 md.connection.close = true; 502   99 md.connection.close = true;
HITCBC 499   55 else if(grammar::ci_is_equal( 503   55 else if(grammar::ci_is_equal(
500   t, "keep-alive")) 504   t, "keep-alive"))
HITCBC 501   28 md.connection.keep_alive = true; 505   28 md.connection.keep_alive = true;
HITCBC 502   27 else if(grammar::ci_is_equal( 506   27 else if(grammar::ci_is_equal(
503   t, "upgrade")) 507   t, "upgrade"))
HITCBC 504   20 md.connection.upgrade = true; 508   20 md.connection.upgrade = true;
505   } 509   }
HITCBC 506   147 } 510   147 }
507   511  
508   void 512   void
HITCBC 509   4558 header:: 513   4558 header::
510   on_insert_content_length( 514   on_insert_content_length(
511   core::string_view v) 515   core::string_view v)
512   { 516   {
513   static 517   static
514   constexpr 518   constexpr
515   grammar::unsigned_rule< 519   grammar::unsigned_rule<
516   std::uint64_t> num_rule{}; 520   std::uint64_t> num_rule{};
517   521  
HITCBC 518   4558 ++md.content_length.count; 522   4558 ++md.content_length.count;
HITCBC 519   4558 if(md.content_length.ec) 523   4558 if(md.content_length.ec)
HITCBC 520   4495 return; 524   4495 return;
521   auto rv = 525   auto rv =
HITCBC 522   4556 grammar::parse(v, num_rule); 526   4556 grammar::parse(v, num_rule);
HITCBC 523   4556 if(! rv) 527   4556 if(! rv)
524   { 528   {
525   // parse failure 529   // parse failure
HITCBC 526   5 md.content_length.ec = 530   5 md.content_length.ec =
HITGIC 527 - error::bad_content_length; 531 + 10 BOOST_HTTP_ERR(
  532 + error::bad_content_length);
HITCBC 528   5 md.content_length.value = 0; 533   5 md.content_length.value = 0;
HITCBC 529   5 update_payload(); 534   5 update_payload();
HITCBC 530   5 return; 535   5 return;
531   } 536   }
HITCBC 532   4551 if(md.content_length.count == 1) 537   4551 if(md.content_length.count == 1)
533   { 538   {
534   // one value 539   // one value
HITCBC 535   4481 md.content_length.ec = {}; 540   4481 md.content_length.ec = {};
HITCBC 536   4481 md.content_length.value = *rv; 541   4481 md.content_length.value = *rv;
HITCBC 537   4481 update_payload(); 542   4481 update_payload();
HITCBC 538   4481 return; 543   4481 return;
539   } 544   }
HITCBC 540   70 if(*rv == md.content_length.value) 545   70 if(*rv == md.content_length.value)
541   { 546   {
542   // ok: duplicate value 547   // ok: duplicate value
HITCBC 543   7 return; 548   7 return;
544   } 549   }
545   // bad: different values 550   // bad: different values
HITCBC 546   63 md.content_length.ec = 551   63 md.content_length.ec =
HITGIC 547 - error::multiple_content_length; 552 + 126 BOOST_HTTP_ERR(
  553 + error::multiple_content_length);
HITCBC 548   63 md.content_length.value = 0; 554   63 md.content_length.value = 0;
HITCBC 549   63 update_payload(); 555   63 update_payload();
550   } 556   }
551   557  
552   void 558   void
HITCBC 553   53 header:: 559   53 header::
554   on_insert_expect( 560   on_insert_expect(
555   core::string_view v) 561   core::string_view v)
556   { 562   {
HITCBC 557   53 ++md.expect.count; 563   53 ++md.expect.count;
HITCBC 558   53 if(kind != detail::kind::request) 564   53 if(kind != detail::kind::request)
HITCBC 559   8 return; 565   8 return;
HITCBC 560   45 if(md.expect.ec) 566   45 if(md.expect.ec)
HITCBC 561   4 return; 567   4 return;
562   // VFALCO Should we allow duplicate 568   // VFALCO Should we allow duplicate
563   // Expect fields that have 100-continue? 569   // Expect fields that have 100-continue?
HITCBC 564   73 if( md.expect.count > 1 || 570   73 if( md.expect.count > 1 ||
HITCBC 565   73 ! grammar::ci_is_equal(v, 571   73 ! grammar::ci_is_equal(v,
566   "100-continue")) 572   "100-continue"))
567   { 573   {
HITCBC 568   19 md.expect.ec = 574   19 md.expect.ec =
HITGIC 569 - error::bad_expect; 575 + 38 BOOST_HTTP_ERR(
  576 + error::bad_expect);
HITCBC 570   19 md.expect.is_100_continue = false; 577   19 md.expect.is_100_continue = false;
HITCBC 571   19 return; 578   19 return;
572   } 579   }
HITCBC 573   22 md.expect.is_100_continue = true; 580   22 md.expect.is_100_continue = true;
574   } 581   }
575   582  
576   void 583   void
HITCBC 577   4415 header:: 584   4415 header::
578   on_insert_transfer_encoding( 585   on_insert_transfer_encoding(
579   core::string_view v) 586   core::string_view v)
580   { 587   {
HITCBC 581   4415 ++md.transfer_encoding.count; 588   4415 ++md.transfer_encoding.count;
HITCBC 582   4415 if(md.transfer_encoding.ec) 589   4415 if(md.transfer_encoding.ec)
HITCBC 583   4407 return; 590   4407 return;
584   591  
585   auto rv = grammar::parse( 592   auto rv = grammar::parse(
HITCBC 586   4414 v, list_rule(transfer_coding_rule, 1)); 593   4414 v, list_rule(transfer_coding_rule, 1));
HITCBC 587   4414 if(! rv) 594   4414 if(! rv)
588   { 595   {
589   // parse error 596   // parse error
HITCBC 590   4 goto error; 597   4 goto error;
591   } 598   }
HITCBC 592   8823 for(auto t : *rv) 599   8823 for(auto t : *rv)
593   { 600   {
HITCBC 594   4417 if(! md.transfer_encoding.is_chunked) 601   4417 if(! md.transfer_encoding.is_chunked)
595   { 602   {
HITCBC 596   4413 if(t.id == transfer_coding_rule_t::chunked) 603   4413 if(t.id == transfer_coding_rule_t::chunked)
HITCBC 597   4394 md.transfer_encoding.is_chunked = true; 604   4394 md.transfer_encoding.is_chunked = true;
HITCBC 598   4413 continue; 605   4413 continue;
599   } 606   }
HITCBC 600   4 if(t.id == transfer_coding_rule_t::chunked) 607   4 if(t.id == transfer_coding_rule_t::chunked)
601   { 608   {
602   // chunked appears twice 609   // chunked appears twice
HITCBC 603   2 goto error; 610   2 goto error;
604   } 611   }
605   // chunked must be last 612   // chunked must be last
HITCBC 606   2 goto error; 613   2 goto error;
HITCBC 607   8831 } 614   8831 }
HITCBC 608   4406 update_payload(); 615   4406 update_payload();
HITCBC 609   4406 return; 616   4406 return;
610   617  
HITCBC 611   8 error: 618   8 error:
HITCBC 612   8 md.transfer_encoding.ec = 619   8 md.transfer_encoding.ec =
HITGIC 613 - error::bad_transfer_encoding; 620 + 16 BOOST_HTTP_ERR(
  621 + error::bad_transfer_encoding);
HITCBC 614   8 md.transfer_encoding.is_chunked = false; 622   8 md.transfer_encoding.is_chunked = false;
HITCBC 615   8 update_payload(); 623   8 update_payload();
HITCBC 616   4414 } 624   4414 }
617   625  
618   void 626   void
HITCBC 619   7 header:: 627   7 header::
620   on_insert_content_encoding( 628   on_insert_content_encoding(
621   core::string_view v) 629   core::string_view v)
622   { 630   {
HITCBC 623   7 ++md.content_encoding.count; 631   7 ++md.content_encoding.count;
HITCBC 624   7 if(md.content_encoding.ec) 632   7 if(md.content_encoding.ec)
HITCBC 625   3 return; 633   3 return;
626   634  
627   auto rv = grammar::parse( 635   auto rv = grammar::parse(
HITCBC 628   7 v, list_rule(token_rule, 1)); 636   7 v, list_rule(token_rule, 1));
HITCBC 629   7 if(!rv) 637   7 if(!rv)
630   { 638   {
HITCBC 631   1 md.content_encoding.ec = 639   1 md.content_encoding.ec =
HITGIC 632 - error::bad_content_encoding; 640 + 2 BOOST_HTTP_ERR(
  641 + error::bad_content_encoding);
HITCBC 633   1 md.content_encoding.coding = 642   1 md.content_encoding.coding =
634   content_coding::unknown; 643   content_coding::unknown;
HITCBC 635   1 return; 644   1 return;
636   } 645   }
637   646  
HITCBC 638   6 if(rv->size() > 1 || md.content_encoding.count > 1) 647   6 if(rv->size() > 1 || md.content_encoding.count > 1)
639   { 648   {
HITCBC 640   2 md.content_encoding.coding = 649   2 md.content_encoding.coding =
641   content_coding::unknown; 650   content_coding::unknown;
HITCBC 642   2 return; 651   2 return;
643   } 652   }
644   653  
HITCBC 645   8 if(grammar::ci_is_equal( 654   8 if(grammar::ci_is_equal(
HITCBC 646   8 *rv->begin(), "deflate")) 655   8 *rv->begin(), "deflate"))
647   { 656   {
MISUBC 648   ✗ md.content_encoding.coding = 657   ✗ md.content_encoding.coding =
649   content_coding::deflate; 658   content_coding::deflate;
650   } 659   }
HITCBC 651   8 else if(grammar::ci_is_equal( 660   8 else if(grammar::ci_is_equal(
HITCBC 652   8 *rv->begin(), "gzip")) 661   8 *rv->begin(), "gzip"))
653   { 662   {
HITCBC 654   2 md.content_encoding.coding = 663   2 md.content_encoding.coding =
655   content_coding::gzip; 664   content_coding::gzip;
656   } 665   }
HITCBC 657   4 else if(grammar::ci_is_equal( 666   4 else if(grammar::ci_is_equal(
HITCBC 658   4 *rv->begin(), "br")) 667   4 *rv->begin(), "br"))
659   { 668   {
HITCBC 660   1 md.content_encoding.coding = 669   1 md.content_encoding.coding =
661   content_coding::br; 670   content_coding::br;
662   } 671   }
HITCBC 663   2 else if(grammar::ci_is_equal( 672   2 else if(grammar::ci_is_equal(
HITCBC 664   2 *rv->begin(), "zstd")) 673   2 *rv->begin(), "zstd"))
665   { 674   {
HITCBC 666   1 md.content_encoding.coding = 675   1 md.content_encoding.coding =
667   content_coding::zstd; 676   content_coding::zstd;
668   } 677   }
669   else 678   else
670   { 679   {
MISUBC 671   ✗ md.content_encoding.coding = 680   ✗ md.content_encoding.coding =
672   content_coding::unknown; 681   content_coding::unknown;
673   } 682   }
HITCBC 674   7 } 683   7 }
675   684  
676   void 685   void
HITCBC 677   26 header:: 686   26 header::
678   on_insert_upgrade( 687   on_insert_upgrade(
679   core::string_view v) 688   core::string_view v)
680   { 689   {
HITCBC 681   26 ++md.upgrade.count; 690   26 ++md.upgrade.count;
HITCBC 682   26 if(md.upgrade.ec) 691   26 if(md.upgrade.ec)
HITCBC 683   5 return; 692   5 return;
HITCBC 684   25 if( version != 693   25 if( version !=
685   http::version::http_1_1) 694   http::version::http_1_1)
686   { 695   {
HITCBC 687   1 md.upgrade.ec = 696   1 md.upgrade.ec =
HITGIC 688 - error::bad_upgrade; 697 + 2 BOOST_HTTP_ERR(
  698 + error::bad_upgrade);
HITCBC 689   1 md.upgrade.websocket = false; 699   1 md.upgrade.websocket = false;
HITCBC 690   1 return; 700   1 return;
691   } 701   }
692   auto rv = grammar::parse( 702   auto rv = grammar::parse(
HITCBC 693   24 v, upgrade_rule); 703   24 v, upgrade_rule);
HITCBC 694   24 if(! rv) 704   24 if(! rv)
695   { 705   {
HITCBC 696   3 md.upgrade.ec = 706   3 md.upgrade.ec =
HITGIC 697 - error::bad_upgrade; 707 + 6 BOOST_HTTP_ERR(
  708 + error::bad_upgrade);
HITCBC 698   3 md.upgrade.websocket = false; 709   3 md.upgrade.websocket = false;
HITCBC 699   3 return; 710   3 return;
700   } 711   }
HITCBC 701   21 if(! md.upgrade.websocket) 712   21 if(! md.upgrade.websocket)
702   { 713   {
HITCBC 703   23 for(auto t : *rv) 714   23 for(auto t : *rv)
704   { 715   {
HITCBC 705   16 if( grammar::ci_is_equal( 716   16 if( grammar::ci_is_equal(
HITCBC 706   26 t.name, "websocket") && 717   26 t.name, "websocket") &&
HITCBC 707   10 t.version.empty()) 718   10 t.version.empty())
708   { 719   {
HITCBC 709   9 md.upgrade.websocket = true; 720   9 md.upgrade.websocket = true;
HITCBC 710   9 break; 721   9 break;
711   } 722   }
712   } 723   }
713   } 724   }
HITCBC 714   24 } 725   24 }
715   726  
716   //------------------------------------------------ 727   //------------------------------------------------
717   728  
718   void 729   void
HITCBC 719   9 header:: 730   9 header::
720   on_erase_connection() 731   on_erase_connection()
721   { 732   {
HITCBC 722   9 BOOST_ASSERT( 733   9 BOOST_ASSERT(
723   md.connection.count > 0); 734   md.connection.count > 0);
724   // reset and re-insert 735   // reset and re-insert
HITCBC 725   9 auto n = md.connection.count - 1; 736   9 auto n = md.connection.count - 1;
HITCBC 726   9 auto const p = cbuf + prefix; 737   9 auto const p = cbuf + prefix;
HITCBC 727   9 auto const* e = &tab()[0]; 738   9 auto const* e = &tab()[0];
HITCBC 728   9 md.connection = {}; 739   9 md.connection = {};
HITCBC 729   17 while(n > 0) 740   17 while(n > 0)
730   { 741   {
HITCBC 731   8 if(e->id == field::connection) 742   8 if(e->id == field::connection)
732   { 743   {
HITCBC 733   7 on_insert_connection( 744   7 on_insert_connection(
734   core::string_view( 745   core::string_view(
HITCBC 735   7 p + e->vp, e->vn)); 746   7 p + e->vp, e->vn));
HITCBC 736   7 --n; 747   7 --n;
737   } 748   }
HITCBC 738   8 --e; 749   8 --e;
739   } 750   }
HITCBC 740   9 } 751   9 }
741   752  
742   void 753   void
HITCBC 743   4 header:: 754   4 header::
744   on_erase_content_length() 755   on_erase_content_length()
745   { 756   {
HITCBC 746   4 BOOST_ASSERT( 757   4 BOOST_ASSERT(
747   md.content_length.count > 0); 758   md.content_length.count > 0);
HITCBC 748   4 --md.content_length.count; 759   4 --md.content_length.count;
HITCBC 749   4 if(md.content_length.count == 0) 760   4 if(md.content_length.count == 0)
750   { 761   {
751   // no Content-Length 762   // no Content-Length
HITCBC 752   1 md.content_length = {}; 763   1 md.content_length = {};
HITCBC 753   1 update_payload(); 764   1 update_payload();
HITCBC 754   1 return; 765   1 return;
755   } 766   }
HITCBC 756   3 if(! md.content_length.ec) 767   3 if(! md.content_length.ec)
757   { 768   {
758   // removing a duplicate value 769   // removing a duplicate value
HITCBC 759   2 return; 770   2 return;
760   } 771   }
761   // reset and re-insert 772   // reset and re-insert
HITCBC 762   1 auto n = md.content_length.count; 773   1 auto n = md.content_length.count;
HITCBC 763   1 auto const p = cbuf + prefix; 774   1 auto const p = cbuf + prefix;
HITCBC 764   1 auto const* e = &tab()[0]; 775   1 auto const* e = &tab()[0];
HITCBC 765   1 md.content_length = {}; 776   1 md.content_length = {};
HITCBC 766   2 while(n > 0) 777   2 while(n > 0)
767   { 778   {
HITCBC 768   1 if(e->id == field::content_length) 779   1 if(e->id == field::content_length)
769   { 780   {
HITCBC 770   1 on_insert_content_length( 781   1 on_insert_content_length(
771   core::string_view( 782   core::string_view(
HITCBC 772   1 p + e->vp, e->vn)); 783   1 p + e->vp, e->vn));
HITCBC 773   1 --n; 784   1 --n;
774   } 785   }
HITCBC 775   1 --e; 786   1 --e;
776   } 787   }
HITCBC 777   1 update_payload(); 788   1 update_payload();
778   } 789   }
779   790  
780   void 791   void
HITCBC 781   10 header:: 792   10 header::
782   on_erase_expect() 793   on_erase_expect()
783   { 794   {
HITCBC 784   10 BOOST_ASSERT( 795   10 BOOST_ASSERT(
785   md.expect.count > 0); 796   md.expect.count > 0);
HITCBC 786   10 --md.expect.count; 797   10 --md.expect.count;
HITCBC 787   10 if(kind != detail::kind::request) 798   10 if(kind != detail::kind::request)
HITCBC 788   1 return; 799   1 return;
HITCBC 789   9 if(md.expect.count == 0) 800   9 if(md.expect.count == 0)
790   { 801   {
791   // no Expect 802   // no Expect
HITCBC 792   3 md.expect = {}; 803   3 md.expect = {};
HITCBC 793   3 return; 804   3 return;
794   } 805   }
795   // VFALCO This should be uncommented 806   // VFALCO This should be uncommented
796   // if we want to allow multiple Expect 807   // if we want to allow multiple Expect
797   // fields with the value 100-continue 808   // fields with the value 100-continue
798   /* 809   /*
799   if(! md.expect.ec) 810   if(! md.expect.ec)
800   return; 811   return;
801   */ 812   */
802   // reset and re-insert 813   // reset and re-insert
HITCBC 803   6 auto n = md.expect.count; 814   6 auto n = md.expect.count;
HITCBC 804   6 auto const p = cbuf + prefix; 815   6 auto const p = cbuf + prefix;
HITCBC 805   6 auto const* e = &tab()[0]; 816   6 auto const* e = &tab()[0];
HITCBC 806   6 md.expect = {}; 817   6 md.expect = {};
HITCBC 807   18 while(n > 0) 818   18 while(n > 0)
808   { 819   {
HITCBC 809   12 if(e->id == field::expect) 820   12 if(e->id == field::expect)
810   { 821   {
HITCBC 811   6 on_insert_expect( 822   6 on_insert_expect(
812   core::string_view( 823   core::string_view(
HITCBC 813   6 p + e->vp, e->vn)); 824   6 p + e->vp, e->vn));
HITCBC 814   6 --n; 825   6 --n;
815   } 826   }
HITCBC 816   12 --e; 827   12 --e;
817   } 828   }
818   } 829   }
819   830  
820   void 831   void
HITCBC 821   4 header:: 832   4 header::
822   on_erase_transfer_encoding() 833   on_erase_transfer_encoding()
823   { 834   {
HITCBC 824   4 BOOST_ASSERT( 835   4 BOOST_ASSERT(
825   md.transfer_encoding.count > 0); 836   md.transfer_encoding.count > 0);
826   // reset and re-insert 837   // reset and re-insert
HITCBC 827   4 auto n = md.transfer_encoding.count - 1; 838   4 auto n = md.transfer_encoding.count - 1;
HITCBC 828   4 auto const p = cbuf + prefix; 839   4 auto const p = cbuf + prefix;
HITCBC 829   4 auto const* e = &tab()[0]; 840   4 auto const* e = &tab()[0];
HITCBC 830   4 md.transfer_encoding = {}; 841   4 md.transfer_encoding = {};
HITCBC 831   7 while(n > 0) 842   7 while(n > 0)
832   { 843   {
HITCBC 833   3 if(e->id == field::transfer_encoding) 844   3 if(e->id == field::transfer_encoding)
834   { 845   {
HITCBC 835   2 on_insert_transfer_encoding( 846   2 on_insert_transfer_encoding(
836   core::string_view( 847   core::string_view(
HITCBC 837   2 p + e->vp, e->vn)); 848   2 p + e->vp, e->vn));
HITCBC 838   2 --n; 849   2 --n;
839   } 850   }
HITCBC 840   3 --e; 851   3 --e;
841   } 852   }
HITCBC 842   4 } 853   4 }
843   854  
844   void 855   void
MISUBC 845   ✗ header:: 856   ✗ header::
846   on_erase_content_encoding() 857   on_erase_content_encoding()
847   { 858   {
MISUBC 848   ✗ BOOST_ASSERT( 859   ✗ BOOST_ASSERT(
849   md.content_encoding.count > 0); 860   md.content_encoding.count > 0);
MISUBC 850   ✗ --md.content_encoding.count; 861   ✗ --md.content_encoding.count;
MISUBC 851   ✗ if(md.content_encoding.count == 0) 862   ✗ if(md.content_encoding.count == 0)
852   { 863   {
853   // no Content-Encoding 864   // no Content-Encoding
MISUBC 854   ✗ md.content_encoding = {}; 865   ✗ md.content_encoding = {};
MISUBC 855   ✗ return; 866   ✗ return;
856   } 867   }
857   // re-insert everything 868   // re-insert everything
MISUBC 858   ✗ --md.content_encoding.count; 869   ✗ --md.content_encoding.count;
859   // TODO 870   // TODO
860   // on_insert_content_encoding(); 871   // on_insert_content_encoding();
861   } 872   }
862   873  
863   // called when Upgrade is erased 874   // called when Upgrade is erased
864   void 875   void
HITCBC 865   4 header:: 876   4 header::
866   on_erase_upgrade() 877   on_erase_upgrade()
867   { 878   {
HITCBC 868   4 BOOST_ASSERT( 879   4 BOOST_ASSERT(
869   md.upgrade.count > 0); 880   md.upgrade.count > 0);
HITCBC 870   4 --md.upgrade.count; 881   4 --md.upgrade.count;
HITCBC 871   4 if(md.upgrade.count == 0) 882   4 if(md.upgrade.count == 0)
872   { 883   {
873   // no Upgrade 884   // no Upgrade
HITCBC 874   2 md.upgrade = {}; 885   2 md.upgrade = {};
HITCBC 875   2 return; 886   2 return;
876   } 887   }
877   // reset and re-insert 888   // reset and re-insert
HITCBC 878   2 auto n = md.upgrade.count; 889   2 auto n = md.upgrade.count;
HITCBC 879   2 auto const p = cbuf + prefix; 890   2 auto const p = cbuf + prefix;
HITCBC 880   2 auto const* e = &tab()[0]; 891   2 auto const* e = &tab()[0];
HITCBC 881   2 md.upgrade = {}; 892   2 md.upgrade = {};
HITCBC 882   4 while(n > 0) 893   4 while(n > 0)
883   { 894   {
HITCBC 884   2 if(e->id == field::upgrade) 895   2 if(e->id == field::upgrade)
HITCBC 885   2 on_insert_upgrade( 896   2 on_insert_upgrade(
886   core::string_view( 897   core::string_view(
HITCBC 887   2 p + e->vp, e->vn)); 898   2 p + e->vp, e->vn));
HITCBC 888   2 --n; 899   2 --n;
HITCBC 889   2 --e; 900   2 --e;
890   } 901   }
891   } 902   }
892   903  
893   //------------------------------------------------ 904   //------------------------------------------------
894   905  
895   // called when all fields with id are removed 906   // called when all fields with id are removed
896   void 907   void
HITCBC 897   72 header:: 908   72 header::
898   on_erase_all( 909   on_erase_all(
899   field id) 910   field id)
900   { 911   {
HITCBC 901   72 if(kind == detail::kind::fields) 912   72 if(kind == detail::kind::fields)
HITCBC 902   21 return; 913   21 return;
HITCBC 903   51 switch(id) 914   51 switch(id)
904   { 915   {
HITCBC 905   3 case field::connection: 916   3 case field::connection:
HITCBC 906   3 md.connection = {}; 917   3 md.connection = {};
HITCBC 907   3 return; 918   3 return;
908   919  
HITCBC 909   2 case field::content_length: 920   2 case field::content_length:
HITCBC 910   2 md.content_length = {}; 921   2 md.content_length = {};
HITCBC 911   2 update_payload(); 922   2 update_payload();
HITCBC 912   2 return; 923   2 return;
913   924  
HITCBC 914   5 case field::expect: 925   5 case field::expect:
HITCBC 915   5 md.expect = {}; 926   5 md.expect = {};
HITCBC 916   5 update_payload(); 927   5 update_payload();
HITCBC 917   5 return; 928   5 return;
918   929  
HITCBC 919   1 case field::transfer_encoding: 930   1 case field::transfer_encoding:
HITCBC 920   1 md.transfer_encoding = {}; 931   1 md.transfer_encoding = {};
HITCBC 921   1 update_payload(); 932   1 update_payload();
HITCBC 922   1 return; 933   1 return;
923   934  
HITCBC 924   1 case field::upgrade: 935   1 case field::upgrade:
HITCBC 925   1 md.upgrade = {}; 936   1 md.upgrade = {};
HITCBC 926   1 return; 937   1 return;
927   938  
HITCBC 928   39 default: 939   39 default:
HITCBC 929   39 break; 940   39 break;
930   } 941   }
931   } 942   }
932   943  
933   //------------------------------------------------ 944   //------------------------------------------------
934   945  
935   /* References: 946   /* References:
936   947  
937   3.3. Message Body 948   3.3. Message Body
938   https://datatracker.ietf.org/doc/html/rfc7230#section-3.3 949   https://datatracker.ietf.org/doc/html/rfc7230#section-3.3
939   950  
940   3.3.1. Transfer-Encoding 951   3.3.1. Transfer-Encoding
941   https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.1 952   https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.1
942   953  
943   3.3.2. Content-Length 954   3.3.2. Content-Length
944   https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2 955   https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2
945   */ 956   */
946   void 957   void
HITCBC 947   19641 header:: 958   19641 header::
948   update_payload() noexcept 959   update_payload() noexcept
949   { 960   {
HITCBC 950   19641 BOOST_ASSERT(kind != 961   19641 BOOST_ASSERT(kind !=
951   detail::kind::fields); 962   detail::kind::fields);
HITCBC 952   19641 if(md.payload_override) 963   19641 if(md.payload_override)
953   { 964   {
954   // e.g. response to 965   // e.g. response to
955   // a HEAD request 966   // a HEAD request
MISUBC 956   ✗ return; 967   ✗ return;
957   } 968   }
958   969  
959   /* If there is an error in either Content-Length 970   /* If there is an error in either Content-Length
960   or Transfer-Encoding, then the payload is 971   or Transfer-Encoding, then the payload is
961   undefined. Clients should probably close the 972   undefined. Clients should probably close the
962   connection. Servers can send a Bad Request 973   connection. Servers can send a Bad Request
963   and avoid reading any payload bytes. 974   and avoid reading any payload bytes.
964   */ 975   */
HITCBC 965   19641 if(md.content_length.ec) 976   19641 if(md.content_length.ec)
966   { 977   {
967   // invalid Content-Length 978   // invalid Content-Length
HITCBC 968   68 md.payload = payload::error; 979   68 md.payload = payload::error;
HITCBC 969   68 md.payload_size = 0; 980   68 md.payload_size = 0;
HITCBC 970   68 return; 981   68 return;
971   } 982   }
HITCBC 972   19573 if(md.transfer_encoding.ec) 983   19573 if(md.transfer_encoding.ec)
973   { 984   {
974   // invalid Transfer-Encoding 985   // invalid Transfer-Encoding
HITCBC 975   8 md.payload = payload::error; 986   8 md.payload = payload::error;
HITCBC 976   8 md.payload_size = 0; 987   8 md.payload_size = 0;
HITCBC 977   8 return; 988   8 return;
978   } 989   }
979   990  
980   /* A sender MUST NOT send a Content-Length 991   /* A sender MUST NOT send a Content-Length
981   header field in any message that contains 992   header field in any message that contains
982   a Transfer-Encoding header field. 993   a Transfer-Encoding header field.
983   https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2 994   https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2
984   */ 995   */
HITCBC 985   19565 if( md.content_length.count > 0 && 996   19565 if( md.content_length.count > 0 &&
HITCBC 986   4485 md.transfer_encoding.count > 0) 997   4485 md.transfer_encoding.count > 0)
987   { 998   {
HITCBC 988   3 md.payload = payload::error; 999   3 md.payload = payload::error;
HITCBC 989   3 md.payload_size = 0; 1000   3 md.payload_size = 0;
HITCBC 990   3 return; 1001   3 return;
991   } 1002   }
992   1003  
HITCBC 993   19562 if(kind == detail::kind::response) 1004   19562 if(kind == detail::kind::response)
HITCBC 994   1924 goto do_response; 1005   1924 goto do_response;
995   1006  
996   //-------------------------------------------- 1007   //--------------------------------------------
997   1008  
998   /* The presence of a message body in a 1009   /* The presence of a message body in a
999   request is signaled by a Content-Length 1010   request is signaled by a Content-Length
1000   or Transfer-Encoding header field. Request 1011   or Transfer-Encoding header field. Request
1001   message framing is independent of method 1012   message framing is independent of method
1002   semantics, even if the method does not 1013   semantics, even if the method does not
1003   define any use for a message body. 1014   define any use for a message body.
1004   */ 1015   */
HITCBC 1005   17638 if(md.content_length.count > 0) 1016   17638 if(md.content_length.count > 0)
1006   { 1017   {
HITCBC 1007   4177 if(md.content_length.value > 0) 1018   4177 if(md.content_length.value > 0)
1008   { 1019   {
1009   // non-zero Content-Length 1020   // non-zero Content-Length
HITCBC 1010   4150 md.payload = payload::size; 1021   4150 md.payload = payload::size;
HITCBC 1011   4150 md.payload_size = md.content_length.value; 1022   4150 md.payload_size = md.content_length.value;
HITCBC 1012   4150 return; 1023   4150 return;
1013   } 1024   }
1014   // Content-Length: 0 1025   // Content-Length: 0
HITCBC 1015   27 md.payload = payload::none; 1026   27 md.payload = payload::none;
HITCBC 1016   27 md.payload_size = 0; 1027   27 md.payload_size = 0;
HITCBC 1017   27 return; 1028   27 return;
1018   } 1029   }
HITCBC 1019   13461 if(md.transfer_encoding.is_chunked) 1030   13461 if(md.transfer_encoding.is_chunked)
1020   { 1031   {
1021   // chunked 1032   // chunked
HITCBC 1022   4012 md.payload = payload::chunked; 1033   4012 md.payload = payload::chunked;
HITCBC 1023   4012 md.payload_size = 0; 1034   4012 md.payload_size = 0;
HITCBC 1024   4012 return; 1035   4012 return;
1025   } 1036   }
1026   // no payload 1037   // no payload
HITCBC 1027   9449 md.payload = payload::none; 1038   9449 md.payload = payload::none;
HITCBC 1028   9449 md.payload_size = 0; 1039   9449 md.payload_size = 0;
HITCBC 1029   9449 return; 1040   9449 return;
1030   1041  
1031   //-------------------------------------------- 1042   //--------------------------------------------
HITCBC 1032   1924 do_response: 1043   1924 do_response:
1033   1044  
HITCBC 1034   1924 if( res.status_int / 100 == 1 || // 1xx e.g. Continue 1045   1924 if( res.status_int / 100 == 1 || // 1xx e.g. Continue
HITCBC 1035   1913 res.status_int == 204 || // No Content 1046   1913 res.status_int == 204 || // No Content
HITCBC 1036   1910 res.status_int == 304) // Not Modified 1047   1910 res.status_int == 304) // Not Modified
1037   { 1048   {
1038   /* The correctness of any Content-Length 1049   /* The correctness of any Content-Length
1039   here is defined by the particular 1050   here is defined by the particular
1040   resource, and cannot be determined 1051   resource, and cannot be determined
1041   here. In any case there is no payload. 1052   here. In any case there is no payload.
1042   */ 1053   */
HITCBC 1043   16 md.payload = payload::none; 1054   16 md.payload = payload::none;
HITCBC 1044   16 md.payload_size = 0; 1055   16 md.payload_size = 0;
HITCBC 1045   16 return; 1056   16 return;
1046   } 1057   }
HITCBC 1047   1908 if(md.content_length.count > 0) 1058   1908 if(md.content_length.count > 0)
1048   { 1059   {
HITCBC 1049   302 if(md.content_length.value > 0) 1060   302 if(md.content_length.value > 0)
1050   { 1061   {
1051   // Content-Length > 0 1062   // Content-Length > 0
HITCBC 1052   283 md.payload = payload::size; 1063   283 md.payload = payload::size;
HITCBC 1053   283 md.payload_size = md.content_length.value; 1064   283 md.payload_size = md.content_length.value;
HITCBC 1054   283 return; 1065   283 return;
1055   } 1066   }
1056   // Content-Length: 0 1067   // Content-Length: 0
HITCBC 1057   19 md.payload = payload::none; 1068   19 md.payload = payload::none;
HITCBC 1058   19 md.payload_size = 0; 1069   19 md.payload_size = 0;
HITCBC 1059   19 return; 1070   19 return;
1060   } 1071   }
HITCBC 1061   1606 if(md.transfer_encoding.is_chunked) 1072   1606 if(md.transfer_encoding.is_chunked)
1062   { 1073   {
1063   // chunked 1074   // chunked
HITCBC 1064   377 md.payload = payload::chunked; 1075   377 md.payload = payload::chunked;
HITCBC 1065   377 md.payload_size = 0; 1076   377 md.payload_size = 0;
HITCBC 1066   377 return; 1077   377 return;
1067   } 1078   }
1068   1079  
1069   // eof needed 1080   // eof needed
HITCBC 1070   1229 md.payload = payload::to_eof; 1081   1229 md.payload = payload::to_eof;
HITCBC 1071   1229 md.payload_size = 0; 1082   1229 md.payload_size = 0;
1072   } 1083   }
1073   1084  
1074   //------------------------------------------------ 1085   //------------------------------------------------
1075   1086  
1076   std::size_t 1087   std::size_t
HITCBC 1077   549 header:: 1088   549 header::
1078   count_crlf( 1089   count_crlf(
1079   core::string_view s) noexcept 1090   core::string_view s) noexcept
1080   { 1091   {
HITCBC 1081   549 auto it = s.data(); 1092   549 auto it = s.data();
HITCBC 1082   549 auto len = s.size(); 1093   549 auto len = s.size();
HITCBC 1083   549 std::size_t n = 0; 1094   549 std::size_t n = 0;
HITCBC 1084   19120 while(len >= 2) 1095   19120 while(len >= 2)
1085   { 1096   {
HITCBC 1086   18571 if( it[0] == '\r' && 1097   18571 if( it[0] == '\r' &&
HITCBC 1087   1749 it[1] != '\r') 1098   1749 it[1] != '\r')
1088   { 1099   {
HITCBC 1089   1749 if(it[1] == '\n') 1100   1749 if(it[1] == '\n')
HITCBC 1090   1749 n++; 1101   1749 n++;
HITCBC 1091   1749 it += 2; 1102   1749 it += 2;
HITCBC 1092   1749 len -= 2; 1103   1749 len -= 2;
1093   } 1104   }
1094   else 1105   else
1095   { 1106   {
HITCBC 1096   16822 it++; 1107   16822 it++;
HITCBC 1097   16822 len--; 1108   16822 len--;
1098   } 1109   }
1099   } 1110   }
HITCBC 1100   549 return n; 1111   549 return n;
1101   } 1112   }
1102   1113  
1103   static 1114   static
1104   void 1115   void
HITCBC 1105   29145 parse_start_line( 1116   29145 parse_start_line(
1106   header& h, 1117   header& h,
1107   header_limits const& lim, 1118   header_limits const& lim,
1108   std::size_t new_size, 1119   std::size_t new_size,
1109 - std::error_code& ec) noexcept 1120 + system::error_code& ec) noexcept
1110   { 1121   {
HITCBC 1111   29145 BOOST_ASSERT(h.size == 0); 1122   29145 BOOST_ASSERT(h.size == 0);
HITCBC 1112   29145 BOOST_ASSERT(h.prefix == 0); 1123   29145 BOOST_ASSERT(h.prefix == 0);
HITCBC 1113   29145 BOOST_ASSERT(h.cbuf != nullptr); 1124   29145 BOOST_ASSERT(h.cbuf != nullptr);
HITCBC 1114   29145 BOOST_ASSERT( 1125   29145 BOOST_ASSERT(
1115   h.kind != detail::kind::fields); 1126   h.kind != detail::kind::fields);
1116   1127  
HITCBC 1117   29145 auto const it0 = h.cbuf; 1128   29145 auto const it0 = h.cbuf;
HITCBC 1118   29145 auto const end = it0 + new_size; 1129   29145 auto const end = it0 + new_size;
HITCBC 1119   29145 char const* it = it0; 1130   29145 char const* it = it0;
HITCBC 1120   29145 if( new_size > lim.max_start_line) 1131   29145 if( new_size > lim.max_start_line)
HITCBC 1121   10 new_size = lim.max_start_line; 1132   10 new_size = lim.max_start_line;
HITCBC 1122   29145 if(h.kind == detail::kind::request) 1133   29145 if(h.kind == detail::kind::request)
1123   { 1134   {
1124   auto rv = grammar::parse( 1135   auto rv = grammar::parse(
HITCBC 1125   11375 it, end, request_line_rule); 1136   11375 it, end, request_line_rule);
HITCBC 1126   11375 if(! rv) 1137   11375 if(! rv)
1127   { 1138   {
HITCBC 1128 - 1991 if( rv.error() != grammar::error::need_more ) 1139 + 1991 ec = rv.error();
HITGBC 1129 - ✗ ec = rv.error(); 1140 + 3982 if( ec == grammar::error::need_more &&
HITCBC 1130 - 1991 else if( new_size == lim.max_start_line ) 1141 + 1991 new_size == lim.max_start_line)
MISUBC 1131 - ✗ ec = error::start_line_limit; 1142 + ✗ ec = BOOST_HTTP_ERR(
1132 - else 1143 + error::start_line_limit);
DCB 1133 - 1991 ec = error::need_data;  
HITCBC 1134   1991 return; 1144   1991 return;
1135   } 1145   }
1136   // method 1146   // method
HITCBC 1137   9384 auto sm = std::get<0>(*rv); 1147   9384 auto sm = std::get<0>(*rv);
HITCBC 1138   9384 h.req.method = string_to_method(sm); 1148   9384 h.req.method = string_to_method(sm);
HITCBC 1139   9384 h.req.method_len = 1149   9384 h.req.method_len =
HITCBC 1140   9384 static_cast<header::offset_type>(sm.size()); 1150   9384 static_cast<header::offset_type>(sm.size());
1141   // target 1151   // target
HITCBC 1142   9384 auto st = std::get<1>(*rv); 1152   9384 auto st = std::get<1>(*rv);
HITCBC 1143   9384 h.req.target_len = 1153   9384 h.req.target_len =
HITCBC 1144   9384 static_cast<header::offset_type>(st.size()); 1154   9384 static_cast<header::offset_type>(st.size());
1145   // version 1155   // version
HITCBC 1146   9384 switch(std::get<2>(*rv)) 1156   9384 switch(std::get<2>(*rv))
1147   { 1157   {
HITCBC 1148   25 case 10: 1158   25 case 10:
HITCBC 1149   25 h.version = 1159   25 h.version =
1150   http::version::http_1_0; 1160   http::version::http_1_0;
HITCBC 1151   25 break; 1161   25 break;
HITCBC 1152   9359 case 11: 1162   9359 case 11:
HITCBC 1153   9359 h.version = 1163   9359 h.version =
1154   http::version::http_1_1; 1164   http::version::http_1_1;
HITCBC 1155   9359 break; 1165   9359 break;
MISUBC 1156   ✗ default: 1166   ✗ default:
1157   { 1167   {
MISUBC 1158 - ✗ ec = error::bad_version; 1168 + ✗ ec = BOOST_HTTP_ERR(
  1169 + error::bad_version);
MISUBC 1159   ✗ return; 1170   ✗ return;
1160   } 1171   }
1161   } 1172   }
1162   } 1173   }
1163   else 1174   else
1164   { 1175   {
1165   auto rv = grammar::parse( 1176   auto rv = grammar::parse(
HITCBC 1166   17770 it, end, status_line_rule); 1177   17770 it, end, status_line_rule);
HITCBC 1167   17770 if(! rv) 1178   17770 if(! rv)
1168   { 1179   {
HITCBC 1169 - 16554 if( rv.error() != grammar::error::need_more ) 1180 + 16554 ec = rv.error();
HITGBC 1170 - ✗ ec = rv.error(); 1181 + 33108 if( ec == grammar::error::need_more &&
HITCBC 1171 - 16554 else if( new_size == lim.max_start_line ) 1182 + 16554 new_size == lim.max_start_line)
MISUBC 1172 - ✗ ec = error::start_line_limit; 1183 + ✗ ec = BOOST_HTTP_ERR(
1173 - else 1184 + error::start_line_limit);
DCB 1174 - 16554 ec = error::need_data;  
HITCBC 1175   16554 return; 1185   16554 return;
1176   } 1186   }
1177   // version 1187   // version
HITCBC 1178   1216 switch(std::get<0>(*rv)) 1188   1216 switch(std::get<0>(*rv))
1179   { 1189   {
HITCBC 1180   4 case 10: 1190   4 case 10:
HITCBC 1181   4 h.version = 1191   4 h.version =
1182   http::version::http_1_0; 1192   http::version::http_1_0;
HITCBC 1183   4 break; 1193   4 break;
HITCBC 1184   1212 case 11: 1194   1212 case 11:
HITCBC 1185   1212 h.version = 1195   1212 h.version =
1186   http::version::http_1_1; 1196   http::version::http_1_1;
HITCBC 1187   1212 break; 1197   1212 break;
MISUBC 1188   ✗ default: 1198   ✗ default:
1189   { 1199   {
MISUBC 1190 - ✗ ec = error::bad_version; 1200 + ✗ ec = BOOST_HTTP_ERR(
  1201 + error::bad_version);
MISUBC 1191   ✗ return; 1202   ✗ return;
1192   } 1203   }
1193   } 1204   }
1194   // status-code 1205   // status-code
HITCBC 1195   1216 h.res.status_int = 1206   1216 h.res.status_int =
1196   static_cast<unsigned short>( 1207   static_cast<unsigned short>(
HITCBC 1197   1216 std::get<1>(*rv).v); 1208   1216 std::get<1>(*rv).v);
HITCBC 1198   1216 h.res.status = std::get<1>(*rv).st; 1209   1216 h.res.status = std::get<1>(*rv).st;
1199   } 1210   }
HITCBC 1200   10600 h.prefix = static_cast<header::offset_type>(it - it0); 1211   10600 h.prefix = static_cast<header::offset_type>(it - it0);
HITCBC 1201   10600 h.size = h.prefix; 1212   10600 h.size = h.prefix;
HITCBC 1202   10600 h.on_start_line(); 1213   10600 h.on_start_line();
1203   } 1214   }
1204   1215  
1205   // returns: true if we added a field 1216   // returns: true if we added a field
1206   static 1217   static
1207   void 1218   void
HITCBC 1208   37744 parse_field( 1219   37744 parse_field(
1209   header& h, 1220   header& h,
1210   header_limits const& lim, 1221   header_limits const& lim,
1211   std::size_t new_size, 1222   std::size_t new_size,
1212 - std::error_code& ec) noexcept 1223 + system::error_code& ec) noexcept
1213   { 1224   {
HITCBC 1214   37744 if( new_size > lim.max_field) 1225   37744 if( new_size > lim.max_field)
HITCBC 1215   20 new_size = lim.max_field; 1226   20 new_size = lim.max_field;
HITCBC 1216   37744 auto const it0 = h.cbuf + h.size; 1227   37744 auto const it0 = h.cbuf + h.size;
HITCBC 1217   37744 auto const end = h.cbuf + new_size; 1228   37744 auto const end = h.cbuf + new_size;
HITCBC 1218   37744 char const* it = it0; 1229   37744 char const* it = it0;
HITCBC 1219   37744 auto rv = grammar::parse( 1230   37744 auto rv = grammar::parse(
1220   it, end, field_rule); 1231   it, end, field_rule);
HITCBC 1221   37744 if(rv.has_error()) 1232   37744 if(rv.has_error())
1222   { 1233   {
HITCBC 1223 - 27030 if(rv.error() == grammar::error::end_of_range) 1234 + 27030 ec = rv.error();
HITGNC   1235 + 27030 if(ec == grammar::error::end_of_range)
1224   { 1236   {
1225   // final CRLF 1237   // final CRLF
HITCBC 1226   10131 h.size = static_cast< 1238   10131 h.size = static_cast<
DCB 1227 - 10131 ec = error::end_of_message;  
HITCBC 1228   10131 header::offset_type>(it - h.cbuf); 1239   10131 header::offset_type>(it - h.cbuf);
HITCBC 1229   27030 return; 1240   27030 return;
1230   } 1241   }
HITCBC 1231 - 16899 if( rv.error() != grammar::error::need_more ) 1242 + 33539 if( ec == grammar::error::need_more &&
HITCBC 1232 - 259 ec = rv.error(); 1243 + 16640 new_size == lim.max_field)
ECB 1233 - 16640 else if( new_size == lim.max_field ) 1244 + {
MISUBC 1234 - ✗ ec = error::field_size_limit; 1245 + ✗ ec = BOOST_HTTP_ERR(
1235 - else 1246 + error::field_size_limit);
ECB 1236 - 16640 ec = error::need_data; 1247 + }
HITCBC 1237   16899 return; 1248   16899 return;
1238   } 1249   }
HITCBC 1239   10714 if(h.count >= lim.max_fields) 1250   10714 if(h.count >= lim.max_fields)
1240   { 1251   {
MISUBC 1241 - ✗ ec = error::fields_limit; 1252 + ✗ ec = BOOST_HTTP_ERR(
  1253 + error::fields_limit);
MISUBC 1242   ✗ return; 1254   ✗ return;
1243   } 1255   }
HITCBC 1244   10714 if(rv->has_obs_fold) 1256   10714 if(rv->has_obs_fold)
1245   { 1257   {
1246   // obs fold not allowed in test views 1258   // obs fold not allowed in test views
HITCBC 1247   210 BOOST_ASSERT(h.buf != nullptr); 1259   210 BOOST_ASSERT(h.buf != nullptr);
HITCBC 1248   210 remove_obs_fold(h.buf + h.size, it); 1260   210 remove_obs_fold(h.buf + h.size, it);
1249   } 1261   }
HITCBC 1250   10714 auto id = string_to_field(rv->name) 1262   10714 auto id = string_to_field(rv->name)
HITCBC 1251   10714 .value_or(header::unknown_field); 1263   10714 .value_or(header::unknown_field);
HITCBC 1252   10714 h.size = static_cast<header::offset_type>(it - h.cbuf); 1264   10714 h.size = static_cast<header::offset_type>(it - h.cbuf);
1253   1265  
1254   // add field table entry 1266   // add field table entry
HITCBC 1255   10714 if(h.buf != nullptr) 1267   10714 if(h.buf != nullptr)
1256   { 1268   {
HITCBC 1257   21428 auto& e = header::table( 1269   21428 auto& e = header::table(
HITCBC 1258   10714 h.buf + h.cap)[h.count]; 1270   10714 h.buf + h.cap)[h.count];
HITCBC 1259   10714 auto const base = 1271   10714 auto const base =
HITCBC 1260   10714 h.buf + h.prefix; 1272   10714 h.buf + h.prefix;
HITCBC 1261   10714 e.np = static_cast<header::offset_type>( 1273   10714 e.np = static_cast<header::offset_type>(
HITCBC 1262   10714 rv->name.data() - base); 1274   10714 rv->name.data() - base);
HITCBC 1263   10714 e.nn = static_cast<header::offset_type>( 1275   10714 e.nn = static_cast<header::offset_type>(
HITCBC 1264   10714 rv->name.size()); 1276   10714 rv->name.size());
HITCBC 1265   10714 e.vp = static_cast<header::offset_type>( 1277   10714 e.vp = static_cast<header::offset_type>(
HITCBC 1266   10714 rv->value.data() - base); 1278   10714 rv->value.data() - base);
HITCBC 1267   10714 e.vn = static_cast<header::offset_type>( 1279   10714 e.vn = static_cast<header::offset_type>(
HITCBC 1268   10714 rv->value.size()); 1280   10714 rv->value.size());
HITCBC 1269   10714 e.id = id; 1281   10714 e.id = id;
1270   } 1282   }
HITCBC 1271   10714 ++h.count; 1283   10714 ++h.count;
HITCBC 1272   10714 h.on_insert(id, rv->value); 1284   10714 h.on_insert(id, rv->value);
HITCBC 1273   10714 ec = {}; 1285   10714 ec = {};
1274   } 1286   }
1275   1287  
1276   void 1288   void
HITCBC 1277   45575 header:: 1289   45575 header::
1278   parse( 1290   parse(
1279   std::size_t new_size, 1291   std::size_t new_size,
1280   header_limits const& lim, 1292   header_limits const& lim,
1281 - std::error_code& ec) noexcept 1293 + system::error_code& ec) noexcept
1282   { 1294   {
HITCBC 1283   45575 if( new_size > lim.max_size) 1295   45575 if( new_size > lim.max_size)
HITCBC 1284   10 new_size = lim.max_size; 1296   10 new_size = lim.max_size;
HITCBC 1285   45575 if( this->prefix == 0 && 1297   45575 if( this->prefix == 0 &&
HITCBC 1286   29379 this->kind != 1298   29379 this->kind !=
1287   detail::kind::fields) 1299   detail::kind::fields)
1288   { 1300   {
HITCBC 1289   29145 parse_start_line( 1301   29145 parse_start_line(
1290   *this, lim, new_size, ec); 1302   *this, lim, new_size, ec);
HITCBC 1291   29145 if(ec) 1303   29145 if(ec)
1292   { 1304   {
HITCBC 1293 - 37090 if( ec == error::need_data && 1305 + 37090 if( ec == grammar::error::need_more &&
HITCBC 1294   18545 new_size == lim.max_fields) 1306   18545 new_size == lim.max_fields)
1295   { 1307   {
MISUBC 1296 - ✗ ec = error::headers_limit; 1308 + ✗ ec = BOOST_HTTP_ERR(
  1309 + error::headers_limit);
1297   } 1310   }
HITCBC 1298   18545 return; 1311   18545 return;
1299   } 1312   }
1300   } 1313   }
1301   for(;;) 1314   for(;;)
1302   { 1315   {
HITCBC 1303   37744 parse_field( 1316   37744 parse_field(
1304   *this, lim, new_size, ec); 1317   *this, lim, new_size, ec);
HITCBC 1305   37744 if(ec) 1318   37744 if(ec)
1306   { 1319   {
HITCBC 1307 - 43670 if( ec == error::need_data && 1320 + 43670 if( ec == grammar::error::need_more &&
HITCBC 1308   16640 new_size == lim.max_size) 1321   16640 new_size == lim.max_size)
1309   { 1322   {
MISUBC 1310 - ✗ ec = error::headers_limit; 1323 + ✗ ec = BOOST_HTTP_ERR(
  1324 + error::headers_limit);
MISUBC 1311   ✗ return; 1325   ✗ return;
1312   } 1326   }
HITCBC 1313   27030 break; 1327   27030 break;
1314   } 1328   }
HITGIC 1315   } 1329   10714 }
HITCBC 1316 - 27030 if(ec == error::end_of_message) 1330 + 27030 if(ec == grammar::error::end_of_range)
HITCBC 1317   10131 ec = {}; 1331   10131 ec = {};
1318   } 1332   }
1319   1333  
1320   } // detail 1334   } // detail
1321   } // http 1335   } // http
1322   } // boost 1336   } // boost