mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 12:57:31 +02:00
Remove deprecated example http::stream wrapper
This commit is contained in:
@ -1,6 +1,11 @@
|
|||||||
1.0.0-b7
|
1.0.0-b7
|
||||||
|
|
||||||
|
* Fix prepare by calling init. prepare() can throw depending on the
|
||||||
|
implementation of Writer. Publicly provided beast::http writers never throw.
|
||||||
|
* Fixes to example HTTP server
|
||||||
* Fully qualify ambiguous calls to read and parse
|
* Fully qualify ambiguous calls to read and parse
|
||||||
|
* Remove deprecated http::stream wrapper
|
||||||
|
* Example HTTP server now calculates the MIME-type
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -1,480 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
|
||||||
//
|
|
||||||
// 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)
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef BEAST_HTTP_STREAM_H_INCLUDED
|
|
||||||
#define BEAST_HTTP_STREAM_H_INCLUDED
|
|
||||||
|
|
||||||
#include <beast/core/async_completion.hpp>
|
|
||||||
#include <beast/core/basic_streambuf.hpp>
|
|
||||||
#include <beast/http.hpp>
|
|
||||||
#include <boost/asio/io_service.hpp>
|
|
||||||
#include <boost/intrusive/list.hpp>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
namespace http {
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
class stream_base
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
struct op
|
|
||||||
: boost::intrusive::list_base_hook<
|
|
||||||
boost::intrusive::link_mode<
|
|
||||||
boost::intrusive::normal_link>>
|
|
||||||
{
|
|
||||||
virtual ~op() = default;
|
|
||||||
virtual void operator()() = 0;
|
|
||||||
virtual void cancel() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
using op_list = typename boost::intrusive::make_list<
|
|
||||||
op, boost::intrusive::constant_time_size<false>>::type;
|
|
||||||
|
|
||||||
op_list wr_q_;
|
|
||||||
bool wr_active_ = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // detail
|
|
||||||
|
|
||||||
/** Provides message-oriented functionality using HTTP.
|
|
||||||
|
|
||||||
The stream class template provides asynchronous and blocking
|
|
||||||
message-oriented functionality necessary for clients and servers
|
|
||||||
to utilize the HTTP protocol.
|
|
||||||
|
|
||||||
@par Thread Safety
|
|
||||||
@e Distinct @e objects: Safe.@n
|
|
||||||
@e Shared @e objects: Unsafe. The application must ensure that
|
|
||||||
all asynchronous operations are performed within the same
|
|
||||||
implicit or explicit strand.
|
|
||||||
|
|
||||||
@par Example
|
|
||||||
|
|
||||||
To use the class template with an `ip::tcp::socket`, you would write:
|
|
||||||
|
|
||||||
@code
|
|
||||||
http::stream<ip::tcp::socket> hs(io_service);
|
|
||||||
@endcode
|
|
||||||
Alternatively, you can write:
|
|
||||||
@code
|
|
||||||
ip::tcp::socket sock(io_service);
|
|
||||||
http::stream<ip::tcp::socket&> hs(sock);
|
|
||||||
@endcode
|
|
||||||
|
|
||||||
@note A stream object must not be destroyed while there are
|
|
||||||
pending asynchronous operations associated with it.
|
|
||||||
|
|
||||||
@par Concepts
|
|
||||||
AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
|
|
||||||
*/
|
|
||||||
template<class NextLayer,
|
|
||||||
class Allocator = std::allocator<char>>
|
|
||||||
class stream : public detail::stream_base
|
|
||||||
{
|
|
||||||
NextLayer next_layer_;
|
|
||||||
basic_streambuf<Allocator> rd_buf_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// The type of the next layer.
|
|
||||||
using next_layer_type =
|
|
||||||
typename std::remove_reference<NextLayer>::type;
|
|
||||||
|
|
||||||
/// The type of the lowest layer.
|
|
||||||
using lowest_layer_type =
|
|
||||||
typename next_layer_type::lowest_layer_type;
|
|
||||||
|
|
||||||
/// The type of endpoint of the lowest layer.
|
|
||||||
using endpoint_type =
|
|
||||||
typename lowest_layer_type::endpoint_type;
|
|
||||||
|
|
||||||
/// The protocol of the next layer.
|
|
||||||
using protocol_type =
|
|
||||||
typename lowest_layer_type::protocol_type;
|
|
||||||
|
|
||||||
/// The type of resolver of the next layer.
|
|
||||||
using resolver_type =
|
|
||||||
typename protocol_type::resolver;
|
|
||||||
|
|
||||||
/** Destructor.
|
|
||||||
|
|
||||||
@note A stream object must not be destroyed while there
|
|
||||||
are pending asynchronous operations associated with it.
|
|
||||||
*/
|
|
||||||
~stream();
|
|
||||||
|
|
||||||
/** Move constructor.
|
|
||||||
|
|
||||||
Undefined behavior if operations are active or pending.
|
|
||||||
*/
|
|
||||||
stream(stream&&) = default;
|
|
||||||
|
|
||||||
/** Move assignment.
|
|
||||||
|
|
||||||
Undefined behavior if operations are active or pending.
|
|
||||||
*/
|
|
||||||
stream& operator=(stream&&) = default;
|
|
||||||
|
|
||||||
/** Construct a HTTP stream.
|
|
||||||
|
|
||||||
This constructor creates a HTTP stream and initialises
|
|
||||||
the next layer.
|
|
||||||
|
|
||||||
@throws Any exceptions thrown by the Stream constructor.
|
|
||||||
|
|
||||||
@param args The arguments to be passed to initialise the
|
|
||||||
next layer. The arguments are forwarded to the next layer's
|
|
||||||
constructor.
|
|
||||||
*/
|
|
||||||
template<class... Args>
|
|
||||||
explicit
|
|
||||||
stream(Args&&... args);
|
|
||||||
|
|
||||||
/** Get the io_service associated with the stream.
|
|
||||||
|
|
||||||
This function may be used to obtain the io_service object
|
|
||||||
that the stream uses to dispatch handlers for asynchronous
|
|
||||||
operations.
|
|
||||||
|
|
||||||
@return A reference to the io_service object that the stream
|
|
||||||
will use to dispatch handlers. Ownership is not transferred
|
|
||||||
to the caller.
|
|
||||||
*/
|
|
||||||
boost::asio::io_service&
|
|
||||||
get_io_service()
|
|
||||||
{
|
|
||||||
return next_layer_.lowest_layer().get_io_service();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a reference to the next layer.
|
|
||||||
|
|
||||||
This function returns a reference to the next layer
|
|
||||||
in a stack of stream layers.
|
|
||||||
|
|
||||||
@return A reference to the next layer in the stack of
|
|
||||||
stream layers. Ownership is not transferred to the caller.
|
|
||||||
*/
|
|
||||||
next_layer_type&
|
|
||||||
next_layer()
|
|
||||||
{
|
|
||||||
return next_layer_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a reference to the next layer.
|
|
||||||
|
|
||||||
This function returns a reference to the next layer in a
|
|
||||||
stack of stream layers.
|
|
||||||
|
|
||||||
@return A reference to the next layer in the stack of
|
|
||||||
stream layers. Ownership is not transferred to the caller.
|
|
||||||
*/
|
|
||||||
next_layer_type const&
|
|
||||||
next_layer() const
|
|
||||||
{
|
|
||||||
return next_layer_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a reference to the lowest layer.
|
|
||||||
|
|
||||||
This function returns a reference to the lowest layer
|
|
||||||
in a stack of stream layers.
|
|
||||||
|
|
||||||
@return A reference to the lowest layer in the stack of
|
|
||||||
stream layers. Ownership is not transferred to the caller.
|
|
||||||
*/
|
|
||||||
lowest_layer_type&
|
|
||||||
lowest_layer()
|
|
||||||
{
|
|
||||||
return next_layer_.lowest_layer();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a reference to the lowest layer.
|
|
||||||
|
|
||||||
This function returns a reference to the lowest layer
|
|
||||||
in a stack of stream layers.
|
|
||||||
|
|
||||||
@return A reference to the lowest layer in the stack of
|
|
||||||
stream layers. Ownership is not transferred to the caller.
|
|
||||||
*/
|
|
||||||
lowest_layer_type const&
|
|
||||||
lowest_layer() const
|
|
||||||
{
|
|
||||||
return next_layer_.lowest_layer();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Cancel pending operations.
|
|
||||||
|
|
||||||
This will cancel all of the asynchronous operations pending,
|
|
||||||
including pipelined writes that have not been started. Handlers for
|
|
||||||
canceled writes will be called with
|
|
||||||
`boost::asio::error::operation_aborted`.
|
|
||||||
|
|
||||||
@throws boost::system::system_error Thrown on failure.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
cancel()
|
|
||||||
{
|
|
||||||
error_code ec;
|
|
||||||
cancel(ec);
|
|
||||||
if(ec)
|
|
||||||
throw system_error{ec};
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Cancel pending operations.
|
|
||||||
|
|
||||||
This will cancel all of the asynchronous operations pending,
|
|
||||||
including pipelined writes that have not been started. Handlers for
|
|
||||||
canceled writes will be called with
|
|
||||||
`boost::asio::error::operation_aborted`.
|
|
||||||
|
|
||||||
@param ec Set to indicate what error occurred, if any.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
cancel(error_code& ec);
|
|
||||||
|
|
||||||
/** Read a HTTP message from the stream.
|
|
||||||
|
|
||||||
This function is used to read a single HTTP message from the stream.
|
|
||||||
The call will block until one of the followign conditions is true:
|
|
||||||
|
|
||||||
@li A message has been read.
|
|
||||||
|
|
||||||
@li An error occurred.
|
|
||||||
|
|
||||||
The operation is implemented in terms of zero or more calls to the
|
|
||||||
next layer's `read_some` function.
|
|
||||||
|
|
||||||
@param msg An object used to store the message. The previous
|
|
||||||
contents of the object will be overwritten.
|
|
||||||
|
|
||||||
@throws boost::system::system_error Thrown on failure.
|
|
||||||
*/
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
void
|
|
||||||
read(message_v1<isRequest, Body, Headers>& msg)
|
|
||||||
{
|
|
||||||
error_code ec;
|
|
||||||
read(msg, ec);
|
|
||||||
if(ec)
|
|
||||||
throw system_error{ec};
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Read a HTTP message from the stream.
|
|
||||||
|
|
||||||
This function is used to read a single HTTP message from the stream.
|
|
||||||
The call will block until one of the followign conditions is true:
|
|
||||||
|
|
||||||
@li A message has been read.
|
|
||||||
|
|
||||||
@li An error occurred.
|
|
||||||
|
|
||||||
The operation is implemented in terms of zero or more calls to the
|
|
||||||
next layer's `read_some` function.
|
|
||||||
|
|
||||||
@param msg An object used to store the message. The previous
|
|
||||||
contents of the object will be overwritten.
|
|
||||||
|
|
||||||
@param ec Set to indicate what error occurred, if any.
|
|
||||||
*/
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
void
|
|
||||||
read(message_v1<isRequest, Body, Headers>& msg,
|
|
||||||
error_code& ec);
|
|
||||||
|
|
||||||
/** Start reading a HTTP message from the stream asynchronously.
|
|
||||||
|
|
||||||
This function is used to asynchronously read a single HTTP message
|
|
||||||
from the stream. The function call always returns immediately. The
|
|
||||||
asynchronous operation will continue until one of the following
|
|
||||||
conditions is true:
|
|
||||||
|
|
||||||
@li The message has been written.
|
|
||||||
|
|
||||||
@li An error occurred.
|
|
||||||
|
|
||||||
This operation is implemented in terms of zero or more calls to the
|
|
||||||
next layer's async_read_some function, and is known as a composed
|
|
||||||
operation. The program must ensure that the stream performs no other
|
|
||||||
read operations or any other composed operations that perform reads
|
|
||||||
until this operation completes.
|
|
||||||
|
|
||||||
@param msg An object used to store the message. The previous
|
|
||||||
contents of the object will be overwritten. Ownership of the message
|
|
||||||
is not transferred; the caller must guarantee that the object remains
|
|
||||||
valid until the handler is called.
|
|
||||||
|
|
||||||
@param handler The handler to be called when the request completes.
|
|
||||||
Copies will be made of the handler as required. The equivalent
|
|
||||||
function signature of the handler must be:
|
|
||||||
@code void handler(
|
|
||||||
error_code const& error // result of operation
|
|
||||||
); @endcode
|
|
||||||
Regardless of whether the asynchronous operation completes
|
|
||||||
immediately or not, the handler will not be invoked from within
|
|
||||||
this function. Invocation of the handler will be performed in a
|
|
||||||
manner equivalent to using boost::asio::io_service::post().
|
|
||||||
*/
|
|
||||||
template<bool isRequest, class Body, class Headers,
|
|
||||||
class ReadHandler>
|
|
||||||
#if GENERATING_DOCS
|
|
||||||
void_or_deduced
|
|
||||||
#else
|
|
||||||
typename async_completion<
|
|
||||||
ReadHandler, void(error_code)>::result_type
|
|
||||||
#endif
|
|
||||||
async_read(message_v1<isRequest, Body, Headers>& msg,
|
|
||||||
ReadHandler&& handler);
|
|
||||||
|
|
||||||
/** Write a HTTP message to the stream.
|
|
||||||
|
|
||||||
This function is used to write a single HTTP message to the
|
|
||||||
stream. The call will block until one of the following conditions
|
|
||||||
is true:
|
|
||||||
|
|
||||||
@li The entire message is sent.
|
|
||||||
|
|
||||||
@li An error occurred.
|
|
||||||
|
|
||||||
If the semantics of the message require that the connection is
|
|
||||||
closed to indicate the end of the content body,
|
|
||||||
`boost::asio::error::eof` is thrown after the message is sent.
|
|
||||||
successfuly. The caller is responsible for actually closing the
|
|
||||||
connection. For regular TCP/IP streams this means shutting down the
|
|
||||||
send side, while SSL streams may call the SSL shutdown function.
|
|
||||||
|
|
||||||
@param msg The message to send.
|
|
||||||
|
|
||||||
@throws boost::system::system_error Thrown on failure.
|
|
||||||
*/
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
void
|
|
||||||
write(message_v1<isRequest, Body, Headers> const& msg)
|
|
||||||
{
|
|
||||||
error_code ec;
|
|
||||||
write(msg, ec);
|
|
||||||
if(ec)
|
|
||||||
throw system_error{ec};
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Write a HTTP message to the stream.
|
|
||||||
|
|
||||||
This function is used to write a single HTTP message to the
|
|
||||||
stream. The call will block until one of the following conditions
|
|
||||||
is true:
|
|
||||||
|
|
||||||
@li The entire message is sent.
|
|
||||||
|
|
||||||
@li An error occurred.
|
|
||||||
|
|
||||||
If the semantics of the message require that the connection is
|
|
||||||
closed to indicate the end of the content body,
|
|
||||||
`boost::asio::error::eof` is returned after the message is sent.
|
|
||||||
successfuly. The caller is responsible for actually closing the
|
|
||||||
connection. For regular TCP/IP streams this means shutting down the
|
|
||||||
send side, while SSL streams may call the SSL shutdown function.
|
|
||||||
|
|
||||||
@param msg The message to send.
|
|
||||||
|
|
||||||
@param ec Set to the error, if any occurred.
|
|
||||||
*/
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
void
|
|
||||||
write(message_v1<isRequest, Body, Headers> const& msg,
|
|
||||||
error_code& ec);
|
|
||||||
|
|
||||||
/** Start pipelining a HTTP message to the stream asynchronously.
|
|
||||||
|
|
||||||
This function is used to queue a message to be sent on the stream.
|
|
||||||
Unlike the free function, this version will place the message on an
|
|
||||||
outgoing message queue if there is already a write pending.
|
|
||||||
|
|
||||||
If the semantics of the message require that the connection is
|
|
||||||
closed to indicate the end of the content body, the handler
|
|
||||||
is called with the error `boost::asio::error::eof` after the message
|
|
||||||
has been sent successfully. The caller is responsible for actually
|
|
||||||
closing the connection. For regular TCP/IP streams this means
|
|
||||||
shutting down the send side, while SSL streams may call the SSL
|
|
||||||
`async_shutdown` function.
|
|
||||||
|
|
||||||
@param msg The message to send. A copy of the message will be made.
|
|
||||||
|
|
||||||
@param handler The handler to be called when the request completes.
|
|
||||||
Copies will be made of the handler as required. The equivalent
|
|
||||||
function signature of the handler must be:
|
|
||||||
@code void handler(
|
|
||||||
error_code const& error // result of operation
|
|
||||||
); @endcode
|
|
||||||
Regardless of whether the asynchronous operation completes
|
|
||||||
immediately or not, the handler will not be invoked from within
|
|
||||||
this function. Invocation of the handler will be performed in a
|
|
||||||
manner equivalent to using boost::asio::io_service::post().
|
|
||||||
*/
|
|
||||||
template<bool isRequest, class Body, class Headers,
|
|
||||||
class WriteHandler>
|
|
||||||
#if GENERATING_DOCS
|
|
||||||
void_or_deduced
|
|
||||||
#else
|
|
||||||
typename async_completion<
|
|
||||||
WriteHandler, void(error_code)>::result_type
|
|
||||||
#endif
|
|
||||||
async_write(message_v1<isRequest, Body, Headers> const& msg,
|
|
||||||
WriteHandler&& handler);
|
|
||||||
|
|
||||||
/** Start pipelining a HTTP message to the stream asynchronously.
|
|
||||||
|
|
||||||
This function is used to queue a message to be sent on the stream.
|
|
||||||
Unlike the free function, this version will place the message on an
|
|
||||||
outgoing message queue if there is already a write pending.
|
|
||||||
|
|
||||||
If the semantics of the message require that the connection is
|
|
||||||
closed to indicate the end of the content body, the handler
|
|
||||||
is called with the error boost::asio::error::eof. The caller is
|
|
||||||
responsible for actually closing the connection. For regular
|
|
||||||
TCP/IP streams this means shutting down the send side, while SSL
|
|
||||||
streams may call the SSL async_shutdown function.
|
|
||||||
|
|
||||||
@param msg The message to send. Ownership of the message, which
|
|
||||||
must be movable, is transferred to the implementation. The message
|
|
||||||
will not be destroyed until the asynchronous operation completes.
|
|
||||||
|
|
||||||
@param handler The handler to be called when the request completes.
|
|
||||||
Copies will be made of the handler as required. The equivalent
|
|
||||||
function signature of the handler must be:
|
|
||||||
@code void handler(
|
|
||||||
error_code const& error // result of operation
|
|
||||||
); @endcode
|
|
||||||
Regardless of whether the asynchronous operation completes
|
|
||||||
immediately or not, the handler will not be invoked from within
|
|
||||||
this function. Invocation of the handler will be performed in a
|
|
||||||
manner equivalent to using boost::asio::io_service::post().
|
|
||||||
*/
|
|
||||||
template<bool isRequest, class Body, class Headers,
|
|
||||||
class WriteHandler>
|
|
||||||
#if GENERATING_DOCS
|
|
||||||
void_or_deduced
|
|
||||||
#else
|
|
||||||
typename async_completion<
|
|
||||||
WriteHandler, void(error_code)>::result_type
|
|
||||||
#endif
|
|
||||||
async_write(message_v1<isRequest, Body, Headers>&& msg,
|
|
||||||
WriteHandler&& handler);
|
|
||||||
|
|
||||||
private:
|
|
||||||
template<bool, class, class, class> class read_op;
|
|
||||||
template<bool, class, class, class> class write_op;
|
|
||||||
|
|
||||||
void
|
|
||||||
cancel_all();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // http
|
|
||||||
} // beast
|
|
||||||
|
|
||||||
#include "http_stream.ipp"
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,412 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
|
||||||
//
|
|
||||||
// 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)
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef BEAST_HTTP_STREAM_IPP_INCLUDED
|
|
||||||
#define BEAST_HTTP_STREAM_IPP_INCLUDED
|
|
||||||
|
|
||||||
#include <beast/core/bind_handler.hpp>
|
|
||||||
#include <beast/core/handler_alloc.hpp>
|
|
||||||
#include <beast/http/message_v1.hpp>
|
|
||||||
#include <beast/http/read.hpp>
|
|
||||||
#include <beast/http/write.hpp>
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
namespace http {
|
|
||||||
|
|
||||||
template<class NextLayer, class Allocator>
|
|
||||||
template<bool isRequest, class Body, class Headers,
|
|
||||||
class Handler>
|
|
||||||
class stream<NextLayer, Allocator>::read_op
|
|
||||||
{
|
|
||||||
using alloc_type =
|
|
||||||
handler_alloc<char, Handler>;
|
|
||||||
|
|
||||||
struct data
|
|
||||||
{
|
|
||||||
stream<NextLayer>& s;
|
|
||||||
message_v1<isRequest, Body, Headers>& m;
|
|
||||||
Handler h;
|
|
||||||
bool cont;
|
|
||||||
int state = 0;
|
|
||||||
|
|
||||||
template<class DeducedHandler>
|
|
||||||
data(DeducedHandler&& h_, stream<NextLayer>& s_,
|
|
||||||
message_v1<isRequest, Body, Headers>& m_)
|
|
||||||
: s(s_)
|
|
||||||
, m(m_)
|
|
||||||
, h(std::forward<DeducedHandler>(h_))
|
|
||||||
, cont(boost_asio_handler_cont_helpers::
|
|
||||||
is_continuation(h))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
std::shared_ptr<data> d_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
read_op(read_op&&) = default;
|
|
||||||
read_op(read_op const&) = default;
|
|
||||||
|
|
||||||
template<class DeducedHandler, class... Args>
|
|
||||||
read_op(DeducedHandler&& h,
|
|
||||||
stream<NextLayer>& s, Args&&... args)
|
|
||||||
: d_(std::allocate_shared<data>(alloc_type{h},
|
|
||||||
std::forward<DeducedHandler>(h), s,
|
|
||||||
std::forward<Args>(args)...))
|
|
||||||
{
|
|
||||||
(*this)(error_code{}, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator()(error_code const& ec, bool again = true);
|
|
||||||
|
|
||||||
friend
|
|
||||||
void* asio_handler_allocate(
|
|
||||||
std::size_t size, read_op* op)
|
|
||||||
{
|
|
||||||
return boost_asio_handler_alloc_helpers::
|
|
||||||
allocate(size, op->d_->h);
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
void asio_handler_deallocate(
|
|
||||||
void* p, std::size_t size, read_op* op)
|
|
||||||
{
|
|
||||||
return boost_asio_handler_alloc_helpers::
|
|
||||||
deallocate(p, size, op->d_->h);
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
bool asio_handler_is_continuation(read_op* op)
|
|
||||||
{
|
|
||||||
return op->d_->cont;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Function>
|
|
||||||
friend
|
|
||||||
void asio_handler_invoke(Function&& f, read_op* op)
|
|
||||||
{
|
|
||||||
return boost_asio_handler_invoke_helpers::
|
|
||||||
invoke(f, op->d_->h);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class NextLayer, class Allocator>
|
|
||||||
template<bool isRequest, class Body, class Headers, class Handler>
|
|
||||||
void
|
|
||||||
stream<NextLayer, Allocator>::
|
|
||||||
read_op<isRequest, Body, Headers, Handler>::
|
|
||||||
operator()(error_code const& ec, bool again)
|
|
||||||
{
|
|
||||||
auto& d = *d_;
|
|
||||||
d.cont = d.cont || again;
|
|
||||||
while(! ec && d.state != 99)
|
|
||||||
{
|
|
||||||
switch(d.state)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
d.state = 99;
|
|
||||||
beast::http::async_read(d.s.next_layer_,
|
|
||||||
d.s.rd_buf_, d.m, std::move(*this));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
d.h(ec);
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<class NextLayer, class Allocator>
|
|
||||||
template<bool isRequest, class Body, class Headers,
|
|
||||||
class Handler>
|
|
||||||
class stream<NextLayer, Allocator>::write_op : public op
|
|
||||||
{
|
|
||||||
using alloc_type =
|
|
||||||
handler_alloc<char, Handler>;
|
|
||||||
|
|
||||||
struct data
|
|
||||||
{
|
|
||||||
stream<NextLayer>& s;
|
|
||||||
message_v1<isRequest, Body, Headers> m;
|
|
||||||
Handler h;
|
|
||||||
bool cont;
|
|
||||||
int state = 0;
|
|
||||||
|
|
||||||
template<class DeducedHandler>
|
|
||||||
data(DeducedHandler&& h_, stream<NextLayer>& s_,
|
|
||||||
message_v1<isRequest, Body, Headers> const& m_,
|
|
||||||
bool cont_)
|
|
||||||
: s(s_)
|
|
||||||
, m(m_)
|
|
||||||
, h(std::forward<DeducedHandler>(h_))
|
|
||||||
, cont(cont_)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class DeducedHandler>
|
|
||||||
data(DeducedHandler&& h_, stream<NextLayer>& s_,
|
|
||||||
message_v1<isRequest, Body, Headers>&& m_,
|
|
||||||
bool cont_)
|
|
||||||
: s(s_)
|
|
||||||
, m(std::move(m_))
|
|
||||||
, h(std::forward<DeducedHandler>(h_))
|
|
||||||
, cont(cont_)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
std::shared_ptr<data> d_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
write_op(write_op&&) = default;
|
|
||||||
write_op(write_op const&) = default;
|
|
||||||
|
|
||||||
template<class DeducedHandler, class... Args>
|
|
||||||
write_op(DeducedHandler&& h,
|
|
||||||
stream<NextLayer>& s, Args&&... args)
|
|
||||||
: d_(std::allocate_shared<data>(alloc_type{h},
|
|
||||||
std::forward<DeducedHandler>(h), s,
|
|
||||||
std::forward<Args>(args)...))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
operator()() override
|
|
||||||
{
|
|
||||||
(*this)(error_code{}, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cancel() override;
|
|
||||||
|
|
||||||
void operator()(error_code const& ec, bool again = true);
|
|
||||||
|
|
||||||
friend
|
|
||||||
void* asio_handler_allocate(
|
|
||||||
std::size_t size, write_op* op)
|
|
||||||
{
|
|
||||||
return boost_asio_handler_alloc_helpers::
|
|
||||||
allocate(size, op->d_->h);
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
void asio_handler_deallocate(
|
|
||||||
void* p, std::size_t size, write_op* op)
|
|
||||||
{
|
|
||||||
return boost_asio_handler_alloc_helpers::
|
|
||||||
deallocate(p, size, op->d_->h);
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
bool asio_handler_is_continuation(write_op* op)
|
|
||||||
{
|
|
||||||
return op->d_->cont;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Function>
|
|
||||||
friend
|
|
||||||
void asio_handler_invoke(Function&& f, write_op* op)
|
|
||||||
{
|
|
||||||
return boost_asio_handler_invoke_helpers::
|
|
||||||
invoke(f, op->d_->h);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class NextLayer, class Allocator>
|
|
||||||
template<bool isRequest, class Body, class Headers, class Handler>
|
|
||||||
void
|
|
||||||
stream<NextLayer, Allocator>::
|
|
||||||
write_op<isRequest, Body, Headers, Handler>::
|
|
||||||
cancel()
|
|
||||||
{
|
|
||||||
auto& d = *d_;
|
|
||||||
d.s.get_io_service().post(
|
|
||||||
bind_handler(std::move(*this),
|
|
||||||
boost::asio::error::operation_aborted));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class NextLayer, class Allocator>
|
|
||||||
template<bool isRequest, class Body, class Headers, class Handler>
|
|
||||||
void
|
|
||||||
stream<NextLayer, Allocator>::
|
|
||||||
write_op<isRequest, Body, Headers, Handler>::
|
|
||||||
operator()(error_code const& ec, bool again)
|
|
||||||
{
|
|
||||||
auto& d = *d_;
|
|
||||||
d.cont = d.cont || again;
|
|
||||||
while(! ec && d.state != 99)
|
|
||||||
{
|
|
||||||
switch(d.state)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
d.state = 99;
|
|
||||||
beast::http::async_write(d.s.next_layer_,
|
|
||||||
d.m, std::move(*this));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
d.h(ec);
|
|
||||||
if(! d.s.wr_q_.empty())
|
|
||||||
{
|
|
||||||
auto& op = d.s.wr_q_.front();
|
|
||||||
op();
|
|
||||||
// VFALCO Use allocator
|
|
||||||
delete &op;
|
|
||||||
d.s.wr_q_.pop_front();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d.s.wr_active_ = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<class NextLayer, class Allocator>
|
|
||||||
stream<NextLayer, Allocator>::
|
|
||||||
~stream()
|
|
||||||
{
|
|
||||||
// Can't destroy with pending operations!
|
|
||||||
assert(wr_q_.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class NextLayer, class Allocator>
|
|
||||||
template<class... Args>
|
|
||||||
stream<NextLayer, Allocator>::
|
|
||||||
stream(Args&&... args)
|
|
||||||
: next_layer_(std::forward<Args>(args)...)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class NextLayer, class Allocator>
|
|
||||||
void
|
|
||||||
stream<NextLayer, Allocator>::
|
|
||||||
cancel(error_code& ec)
|
|
||||||
{
|
|
||||||
cancel_all();
|
|
||||||
lowest_layer().cancel(ec);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class NextLayer, class Allocator>
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
void
|
|
||||||
stream<NextLayer, Allocator>::
|
|
||||||
read(message_v1<isRequest, Body, Headers>& msg,
|
|
||||||
error_code& ec)
|
|
||||||
{
|
|
||||||
beast::http::read(next_layer_, rd_buf_, msg, ec);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class NextLayer, class Allocator>
|
|
||||||
template<bool isRequest, class Body, class Headers,
|
|
||||||
class ReadHandler>
|
|
||||||
auto
|
|
||||||
stream<NextLayer, Allocator>::
|
|
||||||
async_read(message_v1<isRequest, Body, Headers>& msg,
|
|
||||||
ReadHandler&& handler) ->
|
|
||||||
typename async_completion<
|
|
||||||
ReadHandler, void(error_code)>::result_type
|
|
||||||
{
|
|
||||||
async_completion<
|
|
||||||
ReadHandler, void(error_code)
|
|
||||||
> completion(handler);
|
|
||||||
read_op<isRequest, Body, Headers,
|
|
||||||
decltype(completion.handler)>{
|
|
||||||
completion.handler, *this, msg};
|
|
||||||
return completion.result.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class NextLayer, class Allocator>
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
void
|
|
||||||
stream<NextLayer, Allocator>::
|
|
||||||
write(message_v1<isRequest, Body, Headers> const& msg,
|
|
||||||
error_code& ec)
|
|
||||||
{
|
|
||||||
beast::http::write(next_layer_, msg, ec);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class NextLayer, class Allocator>
|
|
||||||
template<bool isRequest, class Body, class Headers,
|
|
||||||
class WriteHandler>
|
|
||||||
auto
|
|
||||||
stream<NextLayer, Allocator>::
|
|
||||||
async_write(message_v1<isRequest, Body, Headers> const& msg,
|
|
||||||
WriteHandler&& handler) ->
|
|
||||||
typename async_completion<
|
|
||||||
WriteHandler, void(error_code)>::result_type
|
|
||||||
{
|
|
||||||
async_completion<
|
|
||||||
WriteHandler, void(error_code)> completion(handler);
|
|
||||||
auto const cont = wr_active_ ||
|
|
||||||
boost_asio_handler_cont_helpers::is_continuation(handler);
|
|
||||||
if(! wr_active_)
|
|
||||||
{
|
|
||||||
wr_active_ = true;
|
|
||||||
write_op<isRequest, Body, Headers,
|
|
||||||
decltype(completion.handler)>{
|
|
||||||
completion.handler, *this, msg, cont }();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// VFALCO Use allocator
|
|
||||||
wr_q_.push_back(*new write_op<isRequest, Body, Headers,
|
|
||||||
decltype(completion.handler)>(
|
|
||||||
completion.handler, *this, msg, cont));
|
|
||||||
}
|
|
||||||
return completion.result.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class NextLayer, class Allocator>
|
|
||||||
template<bool isRequest, class Body, class Headers,
|
|
||||||
class WriteHandler>
|
|
||||||
auto
|
|
||||||
stream<NextLayer, Allocator>::
|
|
||||||
async_write(message_v1<isRequest, Body, Headers>&& msg,
|
|
||||||
WriteHandler&& handler) ->
|
|
||||||
typename async_completion<
|
|
||||||
WriteHandler, void(error_code)>::result_type
|
|
||||||
{
|
|
||||||
async_completion<
|
|
||||||
WriteHandler, void(error_code)> completion(handler);
|
|
||||||
auto const cont = wr_active_ ||
|
|
||||||
boost_asio_handler_cont_helpers::is_continuation(handler);
|
|
||||||
if(! wr_active_)
|
|
||||||
{
|
|
||||||
wr_active_ = true;
|
|
||||||
write_op<isRequest, Body, Headers,
|
|
||||||
decltype(completion.handler)>{completion.handler,
|
|
||||||
*this, std::move(msg), cont}();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// VFALCO Use allocator
|
|
||||||
wr_q_.push_back(*new write_op<isRequest, Body, Headers,
|
|
||||||
decltype(completion.handler)>(completion.handler,
|
|
||||||
*this, std::move(msg), cont));
|
|
||||||
}
|
|
||||||
return completion.result.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class NextLayer, class Allocator>
|
|
||||||
void
|
|
||||||
stream<NextLayer, Allocator>::
|
|
||||||
cancel_all()
|
|
||||||
{
|
|
||||||
for(auto it = wr_q_.begin(); it != wr_q_.end();)
|
|
||||||
{
|
|
||||||
auto& op = *it++;
|
|
||||||
op.cancel();
|
|
||||||
// VFALCO Use allocator
|
|
||||||
delete &op;
|
|
||||||
}
|
|
||||||
wr_q_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // http
|
|
||||||
} // beast
|
|
||||||
|
|
||||||
#endif
|
|
Reference in New Issue
Block a user