GCC Code Coverage Report


Directory: libs/http_proto/include/boost/http_proto/
File: boost/http_proto/impl/parser.ipp
Date: 2023-02-27 20:43:06
Exec Total Coverage
Lines: 190 349 54.4%
Functions: 16 23 69.6%
Branches: 68 195 34.9%

Line Branch Exec Source
1 //
2 // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/CPPAlliance/http_proto
8 //
9
10 #ifndef BOOST_HTTP_PROTO_IMPL_PARSER_IPP
11 #define BOOST_HTTP_PROTO_IMPL_PARSER_IPP
12
13 #include <boost/http_proto/parser.hpp>
14 #include <boost/http_proto/context.hpp>
15 #include <boost/http_proto/error.hpp>
16 #include <boost/http_proto/service/zlib_service.hpp>
17 #include <boost/http_proto/detail/except.hpp>
18 #include <boost/buffers/buffer_copy.hpp>
19 #include <boost/url/grammar/ci_string.hpp>
20 #include <boost/assert.hpp>
21 #include <memory>
22
23 namespace boost {
24 namespace http_proto {
25
26 //------------------------------------------------
27 /*
28 Buffer Usage
29
30 | | begin
31 | H | p | | f | read headers
32 | H | p | | T | f | set T body
33 | H | p | | C | T | f | make codec C
34 | H | p | b | C | T | f | decode p into b
35 | H | p | b | C | T | f | read/parse loop
36 | H | | T | f | destroy codec
37 | H | | T | f | finished
38
39 H headers
40 C codec
41 T body
42 f table
43 p partial payload
44 b body data
45
46 - We can compact the headers:
47 move the table downwards to
48 squeeze out the unused space
49
50 A "plain payload" has no actionable transfer
51 encoding.
52
53 A "buffered payload" is any payload which is
54 not plain. A second buffer is required
55 for reading.
56 */
57 //------------------------------------------------
58
59 class parser_service
60 : public service
61 {
62 public:
63 parser::config_base cfg;
64 std::size_t space_needed = 0;
65 std::size_t max_codec = 0;
66 zlib::deflate_decoder_service const*
67 deflate_svc = nullptr;
68
69 parser_service(
70 context& ctx,
71 parser::config_base const& cfg_);
72
73 std::size_t
74 40065 max_overread() const noexcept
75 {
76 return
77 40065 cfg.headers.max_size +
78 40065 cfg.min_buffer;
79 }
80 };
81
82 6 parser_service::
83 parser_service(
84 context& ctx,
85 6 parser::config_base const& cfg_)
86 6 : cfg(cfg_)
87 {
88 /*
89 | fb | cb0 | cb1 | C | T | f |
90
91 fb flat_buffer headers.max_size
92 cb0 circular_buffer min_buffer
93 cb1 circular_buffer min_buffer
94 C codec max_codec
95 T body max_type_erase
96 f table max_table_space
97
98 */
99 // validate
100 //if(cfg.min_prepare > cfg.max_prepare)
101 //detail::throw_invalid_argument();
102
103
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if( cfg.min_buffer < 1 ||
104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 cfg.min_buffer > cfg.body_limit)
105 detail::throw_invalid_argument();
106
107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if(cfg.max_prepare < 1)
108 detail::throw_invalid_argument();
109
110 // VFALCO TODO OVERFLOW CHECING
111 {
112 //fb_.size() - h_.size +
113 //svc_.cfg.min_buffer +
114 //svc_.cfg.min_buffer +
115 //svc_.max_codec;
116 }
117
118 // VFALCO OVERFLOW CHECKING ON THIS
119 6 space_needed +=
120
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 cfg.headers.valid_space_needed();
121
122 // cb0_, cb1_
123 // VFALCO OVERFLOW CHECKING ON THIS
124 6 space_needed +=
125 6 cfg.min_buffer +
126 cfg.min_buffer;
127
128 // T
129 6 space_needed += cfg.max_type_erase;
130
131 // max_codec
132 {
133
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if(cfg.apply_deflate_decoder)
134 {
135 deflate_svc = &ctx.get_service<
136 zlib::deflate_decoder_service>();
137 auto const n =
138 deflate_svc->space_needed();
139 if( max_codec < n)
140 max_codec = n;
141 }
142 }
143 6 space_needed += max_codec;
144 6 }
145
146 void
147 6 install_parser_service(
148 context& ctx,
149 parser::config_base const& cfg)
150 {
151 ctx.make_service<
152 6 parser_service>(cfg);
153 6 }
154
155 //------------------------------------------------
156
157 6646 parser::
158 parser(
159 context& ctx,
160 6646 detail::kind k)
161 : ctx_(ctx)
162 , svc_(ctx.get_service<
163 13292 parser_service>())
164 , h_(detail::empty{k})
165 6646 , st_(state::reset)
166 {
167 6646 auto const n =
168 6646 svc_.space_needed;
169
1/2
✓ Branch 1 taken 6646 times.
✗ Branch 2 not taken.
6646 ws_.allocate(n);
170 6646 h_.cap = n;
171 6646 }
172
173 //------------------------------------------------
174 //
175 // Special Members
176 //
177 //------------------------------------------------
178
179 6646 parser::
180 6646 ~parser()
181 {
182 6646 }
183
184 parser::
185 parser(
186 parser&&) noexcept = default;
187
188 //------------------------------------------------
189 //
190 // Modifiers
191 //
192 //------------------------------------------------
193
194 // prepare for a new stream
195 void
196 6644 parser::
197 reset() noexcept
198 {
199 6644 ws_.clear();
200 6644 st_ = state::start;
201 6644 got_eof_ = false;
202 6644 }
203
204 void
205 6644 parser::
206 start_impl(
207 bool head_response)
208 {
209 6644 std::size_t leftover = 0;
210
1/5
✗ Branch 0 not taken.
✓ Branch 1 taken 6644 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6644 switch(st_)
211 {
212 default:
213 case state::reset:
214 // reset must be called first
215 detail::throw_logic_error();
216
217 6644 case state::start:
218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6644 times.
6644 BOOST_ASSERT(h_.size == 0);
219
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6644 times.
6644 BOOST_ASSERT(fb_.size() == 0);
220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6644 times.
6644 BOOST_ASSERT(! got_eof_);
221 6644 break;
222
223 case state::header:
224 // start() called twice
225 detail::throw_logic_error();
226
227 case state::body:
228 // current message is incomplete
229 detail::throw_logic_error();
230
231 case state::complete:
232 {
233 // overread data is always in cb0_
234
235 if(fb_.size() > 0)
236 {
237 // headers with no body
238 BOOST_ASSERT(h_.size > 0);
239 fb_.consume(h_.size);
240 leftover = fb_.size();
241 // move unused octets to front
242 buffers::buffer_copy(
243 buffers::mutable_buffer(
244 ws_.data(),
245 leftover),
246 fb_.data());
247 }
248 else
249 {
250 // leftover data after body
251 }
252 break;
253 }
254 }
255
256 6644 ws_.clear();
257
258 13288 fb_ = {
259 6644 ws_.data(),
260 6644 svc_.cfg.headers.max_size +
261 6644 svc_.cfg.min_buffer,
262 leftover };
263
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 6644 times.
6644 BOOST_ASSERT(
264 fb_.capacity() == svc_.max_overread());
265
266 13288 h_ = detail::header(
267 6644 detail::empty{h_.kind});
268 6644 h_.buf = reinterpret_cast<
269 6644 char*>(ws_.data());
270 6644 h_.cbuf = h_.buf;
271 6644 h_.cap = ws_.size();
272
273
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6644 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
6644 BOOST_ASSERT(! head_response ||
274 h_.kind == detail::kind::response);
275 6644 head_response_ = head_response;
276
277 6644 body_ = body::in_place;
278 6644 st_ = state::header;
279 6644 }
280
281 auto
282 20356 parser::
283 prepare() ->
284 mutable_buffers_type
285 {
286
2/5
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 19459 times.
✓ Branch 3 taken 897 times.
✗ Branch 4 not taken.
20356 switch(st_)
287 {
288 default:
289 case state::reset:
290 // reset must be called first
291 detail::throw_logic_error();
292
293 case state::start:
294 // start must be called first
295 detail::throw_logic_error();
296
297 19459 case state::header:
298 {
299
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19459 times.
19459 BOOST_ASSERT(h_.size <
300 svc_.cfg.headers.max_size);
301 19459 auto n = fb_.capacity() - fb_.size();
302
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 19459 times.
19459 BOOST_ASSERT(n <= svc_.max_overread());
303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19459 times.
19459 if( n > svc_.cfg.max_prepare)
304 n = svc_.cfg.max_prepare;
305 19459 mbp_[0] = fb_.prepare(n);
306 19459 return mutable_buffers_type(
307 38918 &mbp_[0], 1);
308 }
309
310 897 case state::body:
311 {
312 // buffered payload
313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 897 times.
897 if(body_buf_ != &cb0_)
314 {
315 auto n = cb0_.capacity() -
316 cb0_.size();
317 if( n > svc_.cfg.max_prepare)
318 n = svc_.cfg.max_prepare;
319 mbp_ = cb0_.prepare(n);
320 return mutable_buffers_type(mbp_);
321 }
322
323 // plain payload
324
325
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 897 times.
897 if( body_ == body::in_place ||
326 body_ == body::sink)
327 {
328 897 auto n = cb0_.capacity() -
329 897 cb0_.size();
330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 897 times.
897 if( n > svc_.cfg.max_prepare)
331 n = svc_.cfg.max_prepare;
332 897 mbp_ = cb0_.prepare(n);
333
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 897 times.
897 BOOST_ASSERT(mbp_[1].size() == 0);
334 897 return mutable_buffers_type(
335 1794 &mbp_[0], 1);
336 }
337
338 if(body_ == body::dynamic)
339 {
340 BOOST_ASSERT(dyn_ != nullptr);
341 if(h_.md.payload == payload::size)
342 {
343 // exact size
344 std::size_t n =
345 h_.md.payload_size - dyn_->size();
346 if( n > svc_.cfg.max_prepare)
347 n = svc_.cfg.max_prepare;
348 return dyn_->prepare(n);
349 }
350
351 // heuristic size
352 std::size_t n = svc_.cfg.min_buffer;
353 if( n > svc_.cfg.max_prepare)
354 n = svc_.cfg.max_prepare;
355 return dyn_->prepare(n);
356 }
357
358 // VFALCO TODO
359 if(body_ == body::stream)
360 detail::throw_logic_error();
361
362 // VFALCO TODO
363 detail::throw_logic_error();
364 }
365
366 case state::complete:
367 // We allow the call for callers
368 // who want normalized usage, but
369 // just return a 0-sized sequence.
370 return mutable_buffers_type{};
371 }
372 }
373
374 void
375 20356 parser::
376 commit(
377 std::size_t n)
378 {
379 // Can't commit after eof
380
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20356 times.
20356 if(got_eof_)
381 detail::throw_logic_error();
382
383
2/5
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 19459 times.
✓ Branch 3 taken 897 times.
✗ Branch 4 not taken.
20356 switch(st_)
384 {
385 default:
386 case state::reset:
387 // reset must be called first
388 detail::throw_logic_error();
389
390 case state::start:
391 // forgot to call start()
392 detail::throw_logic_error();
393
394 19459 case state::header:
395 19459 fb_.commit(n);
396 19459 break;
397
398 897 case state::body:
399
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 897 times.
897 if(body_buf_ != &cb0_)
400 {
401 // buffered body
402 cb0_.commit(n);
403 break;
404 }
405
1/2
✓ Branch 0 taken 897 times.
✗ Branch 1 not taken.
897 if(body_ == body::in_place)
406 {
407 897 cb0_.commit(n);
408 897 break;
409 }
410 if(body_ == body::dynamic)
411 {
412 dyn_->commit(n);
413 break;
414 }
415 if(body_ == body::sink)
416 {
417 cb0_.commit(n);
418 break;
419 }
420 if(body_ == body::stream)
421 {
422 // VFALCO TODO
423 detail::throw_logic_error();
424 }
425 break;
426
427 case state::complete:
428 // intended no-op
429 break;
430 }
431 20356 }
432
433 void
434 1450 parser::
435 commit_eof()
436 {
437
1/5
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1450 times.
✗ Branch 4 not taken.
1450 switch(st_)
438 {
439 default:
440 case state::reset:
441 // reset must be called first
442 detail::throw_logic_error();
443
444 case state::start:
445 // forgot to call prepare()
446 detail::throw_logic_error();
447
448 case state::header:
449 got_eof_ = true;
450 break;
451
452 1450 case state::body:
453 1450 got_eof_ = true;
454 1450 break;
455
456 case state::complete:
457 // can't commit eof when complete
458 detail::throw_logic_error();
459 }
460 1450 }
461
462 //-----------------------------------------------
463
464 // process input data then
465 // eof if input data runs out.
466 void
467 21806 parser::
468 parse(
469 system::error_code& ec)
470 {
471 21806 ec = {};
472
2/5
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 19459 times.
✓ Branch 3 taken 2347 times.
✗ Branch 4 not taken.
21806 switch(st_)
473 {
474 default:
475 case state::reset:
476 // reset must be called first
477 detail::throw_logic_error();
478
479 case state::start:
480 // start must be called first
481 detail::throw_logic_error();
482
483 19459 case state::header:
484 {
485
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 19459 times.
19459 BOOST_ASSERT(h_.buf == static_cast<
486 void const*>(ws_.data()));
487
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 19459 times.
19459 BOOST_ASSERT(h_.cbuf == static_cast<
488 void const*>(ws_.data()));
489 19459 auto const new_size = fb_.size();
490 19459 h_.parse(new_size, svc_.cfg.headers, ec);
491
2/2
✓ Branch 2 taken 12815 times.
✓ Branch 3 taken 6644 times.
19459 if(ec == condition::need_more_input)
492 {
493
1/2
✓ Branch 0 taken 12815 times.
✗ Branch 1 not taken.
12815 if(! got_eof_)
494 {
495 // headers incomplete
496 12815 return;
497 }
498 if(h_.size == 0)
499 {
500 // stream closed cleanly
501 ec = BOOST_HTTP_PROTO_ERR(
502 error::end_of_stream);
503 return;
504 }
505
506 // stream closed with a
507 // partial message received
508 ec = BOOST_HTTP_PROTO_ERR(
509 error::incomplete);
510 return;
511 }
512
2/2
✓ Branch 1 taken 128 times.
✓ Branch 2 taken 6516 times.
6644 if(ec.failed())
513 {
514 // other error,
515 //
516 // VFALCO map this to a bad
517 // request or bad response error?
518 //
519 128 st_ = state::reset; // unrecoverable
520 128 return;
521 }
522
523 // headers are complete
524 6516 on_headers(ec);
525
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6516 times.
6516 if(ec.failed())
526 return;
527
2/2
✓ Branch 0 taken 1343 times.
✓ Branch 1 taken 5173 times.
6516 if(st_ == state::complete)
528 1343 break;
529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5173 times.
5173 BOOST_ASSERT(st_ == state::body);
530 BOOST_FALLTHROUGH;
531 }
532
533 case state::body:
534 {
535
1/2
✓ Branch 0 taken 7520 times.
✗ Branch 1 not taken.
7520 if(body_ == body::in_place)
536 {
537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7520 times.
7520 if(filt_)
538 {
539 // apply filter
540 detail::throw_logic_error();
541 }
542
2/2
✓ Branch 0 taken 4338 times.
✓ Branch 1 taken 3182 times.
7520 if(h_.md.payload == payload::size)
543 {
544 4338 if(cb0_.size() <
545
2/2
✓ Branch 0 taken 615 times.
✓ Branch 1 taken 3723 times.
4338 h_.md.payload_size)
546 {
547 1230 ec = BOOST_HTTP_PROTO_ERR(
548 error::need_data);
549 615 return;
550 }
551 3723 st_ = state::complete;
552 3723 break;
553 }
554
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3182 times.
3182 BOOST_ASSERT(h_.md.payload ==
555 payload::to_eof);
556
2/2
✓ Branch 0 taken 1732 times.
✓ Branch 1 taken 1450 times.
3182 if(! got_eof_)
557 {
558 3464 ec = BOOST_HTTP_PROTO_ERR(
559 error::need_data);
560 1732 return;
561 }
562 1450 st_ = state::complete;
563 1450 break;
564 }
565
566 // VFALCO TODO
567 detail::throw_logic_error();
568 }
569
570 case state::complete:
571 {
572 // This is a no-op except when set_body
573 // was called and we have in-place data.
574 switch(body_)
575 {
576 default:
577 case body::in_place:
578 break;
579
580 case body::dynamic:
581 {
582 if(body_buf_->size() == 0)
583 break;
584 BOOST_ASSERT(dyn_->size() == 0);
585 auto n = buffers::buffer_copy(
586 dyn_->prepare(
587 body_buf_->size()),
588 body_buf_->data());
589 body_buf_->consume(n);
590 break;
591 }
592
593 case body::sink:
594 {
595 if(body_buf_->size() == 0)
596 break;
597 auto rv = sink_->write(
598 body_buf_->data(), false);
599 body_buf_->consume(rv.bytes);
600 if(rv.ec.failed())
601 {
602 ec = rv.ec;
603 st_ = state::reset; // unrecoverable
604 return;
605 }
606 break;
607 }
608
609 case body::stream:
610 // VFALCO TODO
611 detail::throw_logic_error();
612 }
613 }
614 }
615 }
616
617 //------------------------------------------------
618
619 auto
620 parser::
621 get_stream() ->
622 stream
623 {
624 // body type already chosen
625 if(body_ != body::in_place)
626 detail::throw_logic_error();
627
628 body_ = body::stream;
629 return stream(*this);
630 }
631
632 core::string_view
633 4543 parser::
634 in_place_body() const
635 {
636 // not in place
637
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4543 times.
4543 if(body_ != body::in_place)
638 detail::throw_logic_error();
639
640 // incomplete
641
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4543 times.
4543 if(st_ != state::complete)
642 detail::throw_logic_error();
643
644 4543 buffers::const_buffer_pair bs = body_buf_->data();
645
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 4543 times.
4543 BOOST_ASSERT(bs[1].size() == 0);
646 9086 return core::string_view(static_cast<
647 4543 char const*>(bs[0].data()),
648 9086 bs[0].size());
649 }
650
651 //------------------------------------------------
652
653 core::string_view
654 parser::
655 release_buffered_data() noexcept
656 {
657 return {};
658 }
659
660 //------------------------------------------------
661 //
662 // Implementation
663 //
664 //------------------------------------------------
665
666 auto
667 5969 parser::
668 safe_get_header() const ->
669 detail::header const*
670 {
671
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5969 times.
5969 switch(st_)
672 {
673 default:
674 case state::start:
675 case state::header:
676 // Headers not received yet
677 detail::throw_logic_error();
678
679 5969 case state::body:
680 case state::complete:
681 // VFALCO check if headers are discarded?
682 5969 break;
683 }
684 5969 return &h_;
685 }
686
687 // Called immediately after
688 // complete headers are received
689 void
690 6516 parser::
691 on_headers(
692 system::error_code& ec)
693 {
694 auto const overread =
695 6516 fb_.size() - h_.size;
696
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6516 times.
6516 BOOST_ASSERT(
697 overread <= svc_.max_overread());
698
699 // reserve headers + table
700 6516 ws_.reserve_front(h_.size);
701 6516 ws_.reserve_back(h_.table_space());
702
703 // no payload
704
2/2
✓ Branch 0 taken 5173 times.
✓ Branch 1 taken 1343 times.
6516 if( h_.md.payload == payload::none ||
705
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5173 times.
5173 head_response_)
706 {
707 // set cb0_ to overread
708 2686 cb0_ = {
709 1343 ws_.data(),
710 1343 fb_.capacity() - h_.size,
711 overread };
712 1343 st_ = state::complete;
713 1343 return;
714 }
715
716 // metadata error
717
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5173 times.
5173 if(h_.md.payload == payload::error)
718 {
719 // VFALCO This needs looking at
720 ec = BOOST_HTTP_PROTO_ERR(
721 error::bad_payload);
722 st_ = state::reset; // unrecoverable
723 return;
724 }
725
726 // calculate filter
727 5173 filt_ = nullptr;
728
729 // plain payload
730
1/2
✓ Branch 0 taken 5173 times.
✗ Branch 1 not taken.
5173 if( h_.md.payload != payload::chunked &&
731
1/2
✓ Branch 0 taken 5173 times.
✗ Branch 1 not taken.
5173 ! filt_)
732 {
733 // payload size is known
734
2/2
✓ Branch 0 taken 3723 times.
✓ Branch 1 taken 1450 times.
5173 if(h_.md.payload == payload::size)
735 {
736 3723 if(h_.md.payload_size >
737
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3723 times.
3723 svc_.cfg.body_limit)
738 {
739 ec = BOOST_HTTP_PROTO_ERR(
740 error::body_too_large);
741 st_ = state::reset; // unrecoverable
742 return;
743 }
744 auto n0 =
745 3723 fb_.capacity() - h_.size +
746 3723 svc_.cfg.min_buffer +
747 3723 svc_.max_codec;
748 // limit the capacity of cb0_ so
749 // that going over max_overread
750 // is impossible.
751
3/6
✓ Branch 0 taken 3723 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3723 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3723 times.
✗ Branch 5 not taken.
7446 if( n0 > h_.md.payload_size &&
752 3723 n0 - h_.md.payload_size >=
753 3723 svc_.max_overread())
754 3723 n0 =
755 3723 h_.md.payload_size +
756 3723 svc_.max_overread();
757
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3723 times.
3723 BOOST_ASSERT(n0 <= ws_.size());
758 3723 cb0_ = {
759 3723 ws_.data(),
760 n0,
761 overread };
762 3723 body_buf_ = &cb0_;
763 3723 st_ = state::body;
764 3723 return;
765 }
766
767 // payload to eof
768 // overread is not applicable
769 auto const n0 =
770 1450 fb_.capacity() - h_.size +
771 1450 svc_.cfg.min_buffer +
772 1450 svc_.max_codec;
773
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1450 times.
1450 BOOST_ASSERT(n0 <= ws_.size());
774 1450 cb0_ = {
775 1450 ws_.data(),
776 n0,
777 overread };
778 1450 body_buf_ = &cb0_;
779 1450 st_ = state::body;
780 1450 return;
781 }
782
783 // buffered payload
784 auto const n0 =
785 fb_.capacity() - h_.size;
786 BOOST_ASSERT(
787 n0 <= svc_.max_overread());
788 auto n1 = svc_.cfg.min_buffer;
789 if(! filt_)
790 n1 += svc_.max_codec;
791 BOOST_ASSERT(
792 n0 + n1 <= ws_.size());
793 cb0_ = {
794 ws_.data(),
795 n0,
796 overread };
797 cb1_ = {
798 ws_.data() + n0,
799 n1 };
800 body_buf_ = &cb1_;
801 st_ = state::body;
802 return;
803 }
804
805 // Called at the end of set_body
806 void
807 parser::
808 on_set_body()
809 {
810 // This function is called after all
811 // limit checking and calculation of
812 // chunked or filter.
813
814 BOOST_ASSERT(got_header());
815
816 if(h_.md.payload == payload::size)
817 {
818 if(body_ == body::dynamic)
819 {
820 dyn_->prepare(
821 h_.md.payload_size);
822 return;
823 }
824 if(body_ == body::sink)
825 {
826 //sink_->size_hint(&h_.md.payload_size);
827 return;
828 }
829 return;
830 }
831
832 return;
833 }
834
835 } // http_proto
836 } // boost
837
838 #endif
839