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