LCOV - code coverage report
Current view: top level - libs/http_proto/src - message_base.cpp (source / functions) Hit Total Coverage
Test: coverage_filtered.info Lines: 98 115 85.2 %
Date: 2024-02-07 16:12:48 Functions: 3 6 50.0 %

          Line data    Source code
       1             : //
       2             : // Copyright (c) 2021 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             : #include <boost/http_proto/message_base.hpp>
      11             : #include <boost/http_proto/rfc/list_rule.hpp>
      12             : #include <boost/http_proto/rfc/token_rule.hpp>
      13             : #include <boost/http_proto/detail/except.hpp>
      14             : #include "detail/number_string.hpp"
      15             : #include <boost/url/grammar/parse.hpp>
      16             : #include <boost/url/grammar/ci_string.hpp>
      17             : 
      18             : namespace boost {
      19             : namespace http_proto {
      20             : 
      21             : void
      22           0 : message_base::
      23             : set_payload_size(
      24             :     std::uint64_t n)
      25             : {
      26             :     //if(! is_head_response())
      27             :     if(true)
      28             :     {
      29             :         // comes first for exception safety
      30           0 :         set_content_length(n);
      31             : 
      32           0 :         set_chunked(false);
      33             :     }
      34             :     else
      35             :     {
      36             :         // VFALCO ?
      37             :     }
      38           0 : }
      39             : 
      40             : void
      41           0 : message_base::
      42             : set_content_length(
      43             :     std::uint64_t n)
      44             : {
      45           0 :     set(field::content_length,
      46           0 :         detail::number_string(n));
      47           0 : }
      48             : 
      49             : void
      50           0 : message_base::
      51             : set_chunked(bool value)
      52             : {
      53           0 :     if(value)
      54             :     {
      55             :         // set chunked
      56           0 :         if(! h_.md.transfer_encoding.is_chunked )
      57             :         {
      58           0 :             append(
      59             :                 field::transfer_encoding,
      60             :                 "chunked");
      61           0 :             return;
      62             :         }
      63             :     }
      64             :     else
      65             :     {
      66             :         // clear chunked
      67             :         // VFALCO ?
      68             :     }
      69             : }
      70             : 
      71             : void
      72          12 : message_base::
      73             : set_keep_alive(bool value)
      74             : {
      75          12 :     if(ph_->md.connection.ec.failed())
      76             :     {
      77             :         // throw? return false?
      78           5 :         return;
      79             :     }
      80             : 
      81          12 :     if(ph_->md.connection.count == 0)
      82             :     {
      83             :         // no Connection field
      84           5 :         switch(ph_->version)
      85             :         {
      86           3 :         default:
      87             :         case version::http_1_1:
      88           3 :             if(! value)
      89           2 :                 set(field::connection, "close");
      90           3 :             break;
      91             : 
      92           2 :         case version::http_1_0:
      93           2 :             if(value)
      94           1 :                 set(field::connection, "keep-alive");
      95           2 :             break;
      96             :         }
      97           5 :         return;
      98             :     }
      99             : 
     100             :     // VFALCO TODO iterate in reverse order,
     101             :     // and cache the last iterator to use
     102             :     // for appending
     103             : 
     104             :     // one or more Connection fields
     105           7 :     auto it = begin();
     106             :     auto const erase_token =
     107          14 :         [&](core::string_view token)
     108             :         {
     109          14 :             while(it != end())
     110             :             {
     111           8 :                 if(it->id != field::connection)
     112             :                 {
     113           0 :                     ++it;
     114           4 :                     continue;
     115             :                 }
     116             :                 auto rv = grammar::parse(
     117           8 :                     it->value,
     118          16 :                     list_rule(token_rule, 1));
     119           8 :                 BOOST_ASSERT(! rv.has_error());
     120           8 :                 BOOST_ASSERT(! rv->empty());
     121           8 :                 auto itv = rv->begin();
     122           8 :                 if(urls::grammar::ci_is_equal(
     123           8 :                     *itv, token))
     124             :                 {
     125           4 :                     if(rv->size() == 1)
     126             :                     {
     127             :                         // only one token
     128           3 :                         it = erase(it);
     129             :                     }
     130             :                     else
     131             :                     {
     132             :                         // first token matches
     133           1 :                         ++itv;
     134           1 :                         set(it,
     135           1 :                             it->value.substr(
     136           2 :                                 (*itv).data() -
     137           1 :                                 it->value.data()));
     138           1 :                         ++it;
     139             :                     }
     140           4 :                     continue;
     141             :                 }
     142             :                 // search remaining tokens
     143           8 :                 std::string s = *itv++;
     144           7 :                 while(itv != rv->end())
     145             :                 {
     146           3 :                     if(! urls::grammar::ci_is_equal(
     147           3 :                         *itv, token))
     148           1 :                         s += ", " + std::string(*itv);
     149           3 :                     ++itv;
     150             :                 }
     151           4 :                 set(it, s);
     152           4 :                 ++it;
     153             :             }
     154           6 :         };
     155           7 :     if(value)
     156             :     {
     157           6 :         if(ph_->md.connection.close)
     158           5 :             erase_token("close");
     159             :     }
     160             :     else
     161             :     {
     162           1 :         if(ph_->md.connection.keep_alive)
     163           1 :             erase_token("keep-alive");
     164             :     }
     165           7 :     switch(ph_->version)
     166             :     {
     167           5 :     default:
     168             :     case version::http_1_1:
     169           5 :         if(! value)
     170             :         {
     171             :             // add one "close" token if needed
     172           0 :             if(! ph_->md.connection.close)
     173           0 :                 append(field::connection, "close");
     174             :         }
     175           5 :         break;
     176             : 
     177           2 :     case version::http_1_0:
     178           2 :         if(value)
     179             :         {
     180             :             // add one "keep-alive" token if needed
     181           1 :             if(! ph_->md.connection.keep_alive)
     182           0 :                 append(field::connection, "keep-alive");
     183             :         }
     184           2 :         break;
     185             :     }
     186             : }
     187             : 
     188             : //------------------------------------------------
     189             : 
     190             : char*
     191          10 : message_base::
     192             : set_prefix_impl(
     193             :     std::size_t n)
     194             : {
     195          10 :     if( n > h_.prefix ||
     196           3 :         h_.buf == nullptr)
     197             :     {
     198             :         // allocate or grow
     199           8 :         if( n > h_.prefix &&
     200             :             static_cast<std::size_t>(
     201           7 :                 n - h_.prefix) >
     202           7 :             static_cast<std::size_t>(
     203           7 :                 max_offset - h_.size))
     204           1 :             detail::throw_length_error();
     205             : 
     206           7 :         auto n0 = detail::header::bytes_needed(
     207           7 :             n + h_.size - h_.prefix,
     208           7 :             h_.count);
     209           7 :         auto buf = new char[n0];
     210           7 :         if(h_.buf != nullptr)
     211             :         {
     212           3 :             std::memcpy(
     213           3 :                 buf + n,
     214           3 :                 h_.buf + h_.prefix,
     215           3 :                 h_.size - h_.prefix);
     216             :             detail::header::table ft(
     217           3 :                 h_.buf + h_.cap);
     218           3 :             h_.copy_table(buf + n0);
     219           3 :             delete[] h_.buf;
     220             :         }
     221             :         else
     222             :         {
     223           4 :             std::memcpy(
     224           4 :                 buf + n,
     225           4 :                 h_.cbuf + h_.prefix,
     226           4 :                 h_.size - h_.prefix);
     227             :         }
     228           7 :         h_.buf = buf;
     229           7 :         h_.cbuf = buf;
     230           7 :         h_.size = static_cast<
     231           7 :             offset_type>(h_.size +
     232           7 :                 n - h_.prefix);
     233           7 :         h_.prefix = static_cast<
     234             :             offset_type>(n);
     235           7 :         h_.cap = n0;
     236           7 :         return h_.buf;
     237             :     }
     238             : 
     239             :     // shrink
     240           2 :     std::memmove(
     241           2 :         h_.buf + n,
     242           2 :         h_.buf + h_.prefix,
     243           2 :         h_.size - h_.prefix);
     244           2 :     h_.size = static_cast<
     245           2 :         offset_type>(h_.size -
     246           2 :             h_.prefix + n);
     247           2 :     h_.prefix = static_cast<
     248             :         offset_type>(n);
     249           2 :     return h_.buf;
     250             : }
     251             : 
     252             : } // http_proto
     253             : } // boost

Generated by: LCOV version 1.15