Files
boost_beast/include/boost/beast/http/impl/serializer.hpp
T

432 lines
10 KiB
C++
Raw Normal View History

2017-05-28 17:04:39 -07:00
//
2019-02-21 07:00:31 -08:00
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
2017-05-28 17:04:39 -07:00
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
2017-07-20 13:40:34 -07:00
// Official repository: https://github.com/boostorg/beast
//
2017-05-28 17:04:39 -07:00
2019-02-22 13:06:43 -08:00
#ifndef BOOST_BEAST_HTTP_IMPL_SERIALIZER_HPP
#define BOOST_BEAST_HTTP_IMPL_SERIALIZER_HPP
2017-05-28 17:04:39 -07:00
2019-03-05 08:25:54 -08:00
#include <boost/beast/core/buffer_traits.hpp>
2017-07-20 13:40:34 -07:00
#include <boost/beast/core/detail/buffers_ref.hpp>
#include <boost/beast/http/error.hpp>
#include <boost/beast/http/status.hpp>
#include <boost/beast/core/detail/config.hpp>
2017-05-28 17:04:39 -07:00
#include <boost/assert.hpp>
#include <ostream>
2017-07-20 13:40:34 -07:00
namespace boost {
2017-05-28 17:04:39 -07:00
namespace beast {
namespace http {
2017-07-09 20:09:30 -07:00
template<
bool isRequest, class Body, class Fields>
2017-05-28 17:04:39 -07:00
void
2017-07-09 20:09:30 -07:00
serializer<isRequest, Body, Fields>::
2017-12-11 10:06:27 -08:00
fwrinit(std::true_type)
2017-05-28 17:04:39 -07:00
{
2017-12-11 10:06:27 -08:00
fwr_.emplace(m_, m_.version(), m_.method());
2017-05-28 17:04:39 -07:00
}
2017-07-09 20:09:30 -07:00
template<
bool isRequest, class Body, class Fields>
2017-05-28 17:04:39 -07:00
void
2017-07-09 20:09:30 -07:00
serializer<isRequest, Body, Fields>::
2017-12-11 10:06:27 -08:00
fwrinit(std::false_type)
2017-05-28 17:04:39 -07:00
{
2017-12-11 10:06:27 -08:00
fwr_.emplace(m_, m_.version(), m_.result_int());
2017-05-28 17:04:39 -07:00
}
2017-07-09 20:09:30 -07:00
template<
bool isRequest, class Body, class Fields>
2017-07-20 22:54:54 -07:00
template<std::size_t I, class Visit>
2017-07-06 20:58:07 -07:00
inline
void
2017-07-09 20:09:30 -07:00
serializer<isRequest, Body, Fields>::
2017-07-06 20:58:07 -07:00
do_visit(error_code& ec, Visit& visit)
{
2017-07-20 22:54:54 -07:00
pv_.template emplace<I>(limit_, v_.template get<I>());
2017-09-15 14:20:10 -07:00
visit(ec, beast::detail::make_buffers_ref(
pv_.template get<I>()));
2017-07-06 20:58:07 -07:00
}
//------------------------------------------------------------------------------
2017-07-09 20:09:30 -07:00
template<
bool isRequest, class Body, class Fields>
serializer<isRequest, Body, Fields>::
serializer(value_type& m)
: m_(m)
, wr_(m_.base(), m_.body())
{
}
2017-07-09 20:09:30 -07:00
template<
bool isRequest, class Body, class Fields>
2017-05-28 17:04:39 -07:00
template<class Visit>
void
2017-07-09 20:09:30 -07:00
serializer<isRequest, Body, Fields>::
next(error_code& ec, Visit&& visit)
2017-05-28 17:04:39 -07:00
{
switch(s_)
{
case do_construct:
{
2017-12-11 10:06:27 -08:00
fwrinit(std::integral_constant<bool,
2017-06-06 17:26:11 -07:00
isRequest>{});
2017-10-24 17:23:38 -07:00
if(m_.chunked())
goto go_init_c;
s_ = do_init;
2018-01-05 17:46:34 -08:00
BOOST_FALLTHROUGH;
}
2017-05-28 17:04:39 -07:00
case do_init:
{
2017-12-11 10:06:27 -08:00
wr_.init(ec);
2017-05-28 17:04:39 -07:00
if(ec)
return;
if(split_)
goto go_header_only;
2017-12-11 10:06:27 -08:00
auto result = wr_.get(ec);
if(ec == error::need_more)
goto go_header_only;
2017-05-28 17:04:39 -07:00
if(ec)
return;
if(! result)
goto go_header_only;
more_ = result->second;
2017-07-20 22:54:54 -07:00
v_.template emplace<2>(
2017-05-28 17:04:39 -07:00
boost::in_place_init,
2017-12-11 10:06:27 -08:00
fwr_->get(),
2017-07-20 22:54:54 -07:00
result->first);
2017-05-28 17:04:39 -07:00
s_ = do_header;
2018-01-05 17:46:34 -08:00
BOOST_FALLTHROUGH;
2017-05-28 17:04:39 -07:00
}
case do_header:
2017-07-20 22:54:54 -07:00
do_visit<2>(ec, visit);
2017-05-28 17:04:39 -07:00
break;
2017-06-06 17:26:11 -07:00
go_header_only:
2017-12-11 10:06:27 -08:00
v_.template emplace<1>(fwr_->get());
2017-06-06 17:26:11 -07:00
s_ = do_header_only;
2018-01-05 17:46:34 -08:00
BOOST_FALLTHROUGH;
2017-05-28 17:04:39 -07:00
case do_header_only:
2017-07-20 22:54:54 -07:00
do_visit<1>(ec, visit);
2017-05-28 17:04:39 -07:00
break;
case do_body:
s_ = do_body + 1;
2018-01-05 17:46:34 -08:00
BOOST_FALLTHROUGH;
2017-05-28 17:04:39 -07:00
case do_body + 1:
{
2017-12-11 10:06:27 -08:00
auto result = wr_.get(ec);
2017-05-28 17:04:39 -07:00
if(ec)
return;
if(! result)
goto go_complete;
more_ = result->second;
2017-07-20 22:54:54 -07:00
v_.template emplace<3>(result->first);
2017-05-28 17:04:39 -07:00
s_ = do_body + 2;
2018-01-05 17:46:34 -08:00
BOOST_FALLTHROUGH;
2017-05-28 17:04:39 -07:00
}
case do_body + 2:
2017-07-20 22:54:54 -07:00
do_visit<3>(ec, visit);
2017-05-28 17:04:39 -07:00
break;
//----------------------------------------------------------------------
2017-10-27 16:05:09 -07:00
go_init_c:
s_ = do_init_c;
2018-01-05 17:46:34 -08:00
BOOST_FALLTHROUGH;
2017-05-28 17:04:39 -07:00
case do_init_c:
{
2017-12-11 10:06:27 -08:00
wr_.init(ec);
2017-05-28 17:04:39 -07:00
if(ec)
return;
if(split_)
goto go_header_only_c;
2017-12-11 10:06:27 -08:00
auto result = wr_.get(ec);
if(ec == error::need_more)
goto go_header_only_c;
2017-05-28 17:04:39 -07:00
if(ec)
return;
if(! result)
goto go_header_only_c;
more_ = result->second;
2017-06-26 18:26:35 -07:00
if(! more_)
{
// do it all in one buffer
2017-07-20 22:54:54 -07:00
v_.template emplace<7>(
2017-06-26 18:26:35 -07:00
boost::in_place_init,
2017-12-11 10:06:27 -08:00
fwr_->get(),
2019-03-05 08:47:02 -08:00
buffer_bytes(result->first),
2018-11-30 14:58:38 -08:00
net::const_buffer{nullptr, 0},
2017-07-09 20:09:30 -07:00
chunk_crlf{},
2017-06-26 18:26:35 -07:00
result->first,
2017-07-09 20:09:30 -07:00
chunk_crlf{},
detail::chunk_last(),
2018-11-30 14:58:38 -08:00
net::const_buffer{nullptr, 0},
2017-07-20 22:54:54 -07:00
chunk_crlf{});
2017-06-26 18:26:35 -07:00
goto go_all_c;
}
2017-07-20 22:54:54 -07:00
v_.template emplace<4>(
2017-05-28 17:04:39 -07:00
boost::in_place_init,
2017-12-11 10:06:27 -08:00
fwr_->get(),
2019-03-05 08:47:02 -08:00
buffer_bytes(result->first),
2018-11-30 14:58:38 -08:00
net::const_buffer{nullptr, 0},
2017-07-09 20:09:30 -07:00
chunk_crlf{},
2017-05-28 17:04:39 -07:00
result->first,
2017-07-20 22:54:54 -07:00
chunk_crlf{});
2017-05-28 17:04:39 -07:00
s_ = do_header_c;
2018-01-05 17:46:34 -08:00
BOOST_FALLTHROUGH;
2017-05-28 17:04:39 -07:00
}
case do_header_c:
2017-07-20 22:54:54 -07:00
do_visit<4>(ec, visit);
2017-05-28 17:04:39 -07:00
break;
2017-06-06 17:26:11 -07:00
go_header_only_c:
2017-12-11 10:06:27 -08:00
v_.template emplace<1>(fwr_->get());
2017-06-06 17:26:11 -07:00
s_ = do_header_only_c;
2018-02-13 11:54:44 +01:00
BOOST_FALLTHROUGH;
2017-05-28 17:04:39 -07:00
case do_header_only_c:
2017-07-20 22:54:54 -07:00
do_visit<1>(ec, visit);
2017-05-28 17:04:39 -07:00
break;
case do_body_c:
s_ = do_body_c + 1;
2018-01-05 17:46:34 -08:00
BOOST_FALLTHROUGH;
2017-05-28 17:04:39 -07:00
case do_body_c + 1:
{
2017-12-11 10:06:27 -08:00
auto result = wr_.get(ec);
2017-05-28 17:04:39 -07:00
if(ec)
return;
if(! result)
goto go_final_c;
more_ = result->second;
2017-06-26 18:26:35 -07:00
if(! more_)
{
// do it all in one buffer
2017-07-20 22:54:54 -07:00
v_.template emplace<6>(
2017-06-26 18:26:35 -07:00
boost::in_place_init,
2019-03-05 08:47:02 -08:00
buffer_bytes(result->first),
2018-11-30 14:58:38 -08:00
net::const_buffer{nullptr, 0},
2017-07-09 20:09:30 -07:00
chunk_crlf{},
2017-06-26 18:26:35 -07:00
result->first,
2017-07-09 20:09:30 -07:00
chunk_crlf{},
detail::chunk_last(),
2018-11-30 14:58:38 -08:00
net::const_buffer{nullptr, 0},
2017-07-20 22:54:54 -07:00
chunk_crlf{});
2017-06-26 18:26:35 -07:00
goto go_body_final_c;
}
2017-07-20 22:54:54 -07:00
v_.template emplace<5>(
2017-05-28 17:04:39 -07:00
boost::in_place_init,
2019-03-05 08:47:02 -08:00
buffer_bytes(result->first),
2018-11-30 14:58:38 -08:00
net::const_buffer{nullptr, 0},
2017-07-09 20:09:30 -07:00
chunk_crlf{},
2017-05-28 17:04:39 -07:00
result->first,
2017-07-20 22:54:54 -07:00
chunk_crlf{});
2017-05-28 17:04:39 -07:00
s_ = do_body_c + 2;
2018-01-05 17:46:34 -08:00
BOOST_FALLTHROUGH;
2017-05-28 17:04:39 -07:00
}
case do_body_c + 2:
2017-07-20 22:54:54 -07:00
do_visit<5>(ec, visit);
2017-05-28 17:04:39 -07:00
break;
2017-06-26 18:26:35 -07:00
go_body_final_c:
s_ = do_body_final_c;
2018-01-05 17:46:34 -08:00
BOOST_FALLTHROUGH;
2017-06-26 18:26:35 -07:00
case do_body_final_c:
2017-07-20 22:54:54 -07:00
do_visit<6>(ec, visit);
2017-06-26 18:26:35 -07:00
break;
go_all_c:
s_ = do_all_c;
2018-01-05 17:46:34 -08:00
BOOST_FALLTHROUGH;
2017-06-26 18:26:35 -07:00
case do_all_c:
2017-07-20 22:54:54 -07:00
do_visit<7>(ec, visit);
2017-06-26 18:26:35 -07:00
break;
go_final_c:
2017-05-28 17:04:39 -07:00
case do_final_c:
2017-07-20 22:54:54 -07:00
v_.template emplace<8>(
2017-05-28 17:04:39 -07:00
boost::in_place_init,
2017-07-09 20:09:30 -07:00
detail::chunk_last(),
2018-11-30 14:58:38 -08:00
net::const_buffer{nullptr, 0},
2017-07-20 22:54:54 -07:00
chunk_crlf{});
2017-05-28 17:04:39 -07:00
s_ = do_final_c + 1;
2018-01-05 17:46:34 -08:00
BOOST_FALLTHROUGH;
2017-05-28 17:04:39 -07:00
case do_final_c + 1:
2017-07-20 22:54:54 -07:00
do_visit<8>(ec, visit);
2017-05-28 17:04:39 -07:00
break;
//----------------------------------------------------------------------
default:
case do_complete:
BOOST_ASSERT(false);
break;
go_complete:
s_ = do_complete;
break;
}
}
2017-07-09 20:09:30 -07:00
template<
bool isRequest, class Body, class Fields>
2017-05-28 17:04:39 -07:00
void
2017-07-09 20:09:30 -07:00
serializer<isRequest, Body, Fields>::
2017-05-28 17:04:39 -07:00
consume(std::size_t n)
{
switch(s_)
{
case do_header:
2017-07-20 22:54:54 -07:00
BOOST_ASSERT(
2019-03-05 08:47:02 -08:00
n <= buffer_bytes(v_.template get<2>()));
2017-07-20 22:54:54 -07:00
v_.template get<2>().consume(n);
2019-03-05 08:47:02 -08:00
if(buffer_bytes(v_.template get<2>()) > 0)
2017-05-28 17:04:39 -07:00
break;
header_done_ = true;
2017-07-20 22:54:54 -07:00
v_.reset();
2017-05-28 17:04:39 -07:00
if(! more_)
goto go_complete;
s_ = do_body + 1;
break;
case do_header_only:
2017-07-20 22:54:54 -07:00
BOOST_ASSERT(
2019-03-05 08:47:02 -08:00
n <= buffer_bytes(v_.template get<1>()));
2017-07-20 22:54:54 -07:00
v_.template get<1>().consume(n);
2019-03-05 08:47:02 -08:00
if(buffer_bytes(v_.template get<1>()) > 0)
2017-05-28 17:04:39 -07:00
break;
2017-12-11 10:06:27 -08:00
fwr_ = boost::none;
2017-05-28 17:04:39 -07:00
header_done_ = true;
if(! split_)
2017-05-28 17:04:39 -07:00
goto go_complete;
s_ = do_body;
break;
case do_body + 2:
{
2017-07-20 22:54:54 -07:00
BOOST_ASSERT(
2019-03-05 08:47:02 -08:00
n <= buffer_bytes(v_.template get<3>()));
2017-07-20 22:54:54 -07:00
v_.template get<3>().consume(n);
2019-03-05 08:47:02 -08:00
if(buffer_bytes(v_.template get<3>()) > 0)
2017-05-28 17:04:39 -07:00
break;
2017-07-20 22:54:54 -07:00
v_.reset();
2017-05-28 17:04:39 -07:00
if(! more_)
goto go_complete;
s_ = do_body + 1;
break;
}
//----------------------------------------------------------------------
case do_header_c:
2017-07-20 22:54:54 -07:00
BOOST_ASSERT(
2019-03-05 08:47:02 -08:00
n <= buffer_bytes(v_.template get<4>()));
2017-07-20 22:54:54 -07:00
v_.template get<4>().consume(n);
2019-03-05 08:47:02 -08:00
if(buffer_bytes(v_.template get<4>()) > 0)
2017-05-28 17:04:39 -07:00
break;
header_done_ = true;
2017-07-20 22:54:54 -07:00
v_.reset();
2017-05-28 17:04:39 -07:00
if(more_)
s_ = do_body_c + 1;
else
s_ = do_final_c;
break;
case do_header_only_c:
{
2017-07-20 22:54:54 -07:00
BOOST_ASSERT(
2019-03-05 08:47:02 -08:00
n <= buffer_bytes(v_.template get<1>()));
2017-07-20 22:54:54 -07:00
v_.template get<1>().consume(n);
2019-03-05 08:47:02 -08:00
if(buffer_bytes(v_.template get<1>()) > 0)
2017-05-28 17:04:39 -07:00
break;
2017-12-11 10:06:27 -08:00
fwr_ = boost::none;
2017-05-28 17:04:39 -07:00
header_done_ = true;
if(! split_)
2017-05-28 17:04:39 -07:00
{
s_ = do_final_c;
break;
}
s_ = do_body_c;
break;
}
case do_body_c + 2:
2017-07-20 22:54:54 -07:00
BOOST_ASSERT(
2019-03-05 08:47:02 -08:00
n <= buffer_bytes(v_.template get<5>()));
2017-07-20 22:54:54 -07:00
v_.template get<5>().consume(n);
2019-03-05 08:47:02 -08:00
if(buffer_bytes(v_.template get<5>()) > 0)
2017-05-28 17:04:39 -07:00
break;
2017-07-20 22:54:54 -07:00
v_.reset();
2017-05-28 17:04:39 -07:00
if(more_)
s_ = do_body_c + 1;
else
s_ = do_final_c;
break;
2017-06-26 18:26:35 -07:00
case do_body_final_c:
{
2017-07-20 22:54:54 -07:00
BOOST_ASSERT(
2019-03-05 08:47:02 -08:00
n <= buffer_bytes(v_.template get<6>()));
2017-07-20 22:54:54 -07:00
v_.template get<6>().consume(n);
2019-03-05 08:47:02 -08:00
if(buffer_bytes(v_.template get<6>()) > 0)
2017-06-26 18:26:35 -07:00
break;
2017-07-20 22:54:54 -07:00
v_.reset();
2017-06-26 18:26:35 -07:00
s_ = do_complete;
break;
}
case do_all_c:
{
2017-07-20 22:54:54 -07:00
BOOST_ASSERT(
2019-03-05 08:47:02 -08:00
n <= buffer_bytes(v_.template get<7>()));
2017-07-20 22:54:54 -07:00
v_.template get<7>().consume(n);
2019-03-05 08:47:02 -08:00
if(buffer_bytes(v_.template get<7>()) > 0)
2017-06-26 18:26:35 -07:00
break;
header_done_ = true;
2017-07-20 22:54:54 -07:00
v_.reset();
2017-06-26 18:26:35 -07:00
s_ = do_complete;
break;
}
2017-05-28 17:04:39 -07:00
case do_final_c + 1:
2019-03-05 08:47:02 -08:00
BOOST_ASSERT(buffer_bytes(v_.template get<8>()));
2017-07-20 22:54:54 -07:00
v_.template get<8>().consume(n);
2019-03-05 08:47:02 -08:00
if(buffer_bytes(v_.template get<8>()) > 0)
2017-05-28 17:04:39 -07:00
break;
2017-07-20 22:54:54 -07:00
v_.reset();
2017-05-28 17:04:39 -07:00
goto go_complete;
//----------------------------------------------------------------------
default:
BOOST_ASSERT(false);
case do_complete:
break;
go_complete:
s_ = do_complete;
break;
}
}
} // http
} // beast
2017-07-20 13:40:34 -07:00
} // boost
2017-05-28 17:04:39 -07:00
#endif