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