mirror of
https://github.com/boostorg/beast.git
synced 2025-08-03 14:54:32 +02:00
Concept revision and documentation (API Change):
The concept type traits are renamed for consistency, and consolidated into a single header file <beast/core/type_traits.hpp> A new section, Core Concepts, is added to the documentation describing all of the core utility classes and functions. This also includes a complete explanation and sample program describing how to write asynchronous initiation functions and their associated composed operations.
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
Version 41
|
Version 41
|
||||||
|
|
||||||
* Trim Appveyor matrix rows
|
* Trim Appveyor matrix rows
|
||||||
|
* Concept revision and documentation
|
||||||
|
|
||||||
API Changes
|
API Changes
|
||||||
|
|
||||||
|
611
doc/core.qbk
Normal file
611
doc/core.qbk
Normal file
@@ -0,0 +1,611 @@
|
|||||||
|
[/
|
||||||
|
Copyright (c) 2013-2017 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)
|
||||||
|
]
|
||||||
|
|
||||||
|
[section:core Core Concepts]
|
||||||
|
|
||||||
|
[block '''
|
||||||
|
<informaltable frame="all"><tgroup cols="1"><colspec colname="a"/><tbody><row><entry valign="top"><simplelist>
|
||||||
|
<member><link linkend="beast.core.concepts">Concepts</link></member>
|
||||||
|
<member><link linkend="beast.core.dynamic_buffer">DynamicBuffer</link></member>
|
||||||
|
<member><link linkend="beast.core.algorithms">Buffer Algorithms</link></member>
|
||||||
|
<member><link linkend="beast.core.async">Asynchronous Model</link></member>
|
||||||
|
<member><link linkend="beast.core.tutorial">Tutorial</link></member>
|
||||||
|
</simplelist></entry></row></tbody></tgroup></informaltable>
|
||||||
|
''']
|
||||||
|
|
||||||
|
In addition to network protocols, Beast provides users with robust concepts,
|
||||||
|
implementations, and algorithms which can be used to design higher level
|
||||||
|
abstractions that interoperate with Boost.Asio. In the sections that follow
|
||||||
|
are descriptions of these concepts, followed by algorithms using the concepts,
|
||||||
|
and then concluding with a tutorial on developing composed asynchronous
|
||||||
|
operations which are compatible with the Extensible Asynchronous Model provided
|
||||||
|
in Boost.Asio, __N3747__, and __N4588__.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[section:concepts Concepts]
|
||||||
|
|
||||||
|
Beast provides template metaprogramming functions to allow users to perform
|
||||||
|
concept checks on parameters, preventing undefined or illegal use. These trait
|
||||||
|
traits are used in the implementation of the library and part of its public
|
||||||
|
interface so users may build on the library using the same features. Use of
|
||||||
|
concept checks benefit users by providing accurate, concise compilation error
|
||||||
|
diagnostics.
|
||||||
|
|
||||||
|
[table Type Traits
|
||||||
|
[[Name][Description]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.has_get_io_service `has_get_io_service`]
|
||||||
|
][
|
||||||
|
Determine if the `get_io_service` member function is present with the
|
||||||
|
correct signature.
|
||||||
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.is_async_read_stream `is_async_read_stream`]
|
||||||
|
][
|
||||||
|
Determine if a type meets the requirements of __AsyncReadStream__.
|
||||||
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.is_async_stream `is_async_stream`]
|
||||||
|
][
|
||||||
|
Determine if a type meets the requirements of both __AsyncReadStream__
|
||||||
|
and __AsyncWriteStream__.
|
||||||
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.is_async_write_stream `is_async_write_stream`]
|
||||||
|
][
|
||||||
|
Determine if a type meets the requirements of __AsyncWriteStream__.
|
||||||
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.is_completion_handler `is_completion_handler`]
|
||||||
|
][
|
||||||
|
Determine if a type meets the requirements of __CompletionHandler__,
|
||||||
|
and is callable with a specified signature.
|
||||||
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.is_const_buffer_sequence `is_const_buffer_sequence`]
|
||||||
|
][
|
||||||
|
Determine if a type meets the requirements of __ConstBufferSequence__.
|
||||||
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.is_dynamic_buffer `is_dynamic_buffer`]
|
||||||
|
][
|
||||||
|
Determine if a type meets the requirements of __DynamicBuffer__.
|
||||||
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.is_mutable_buffer_sequence `is_mutable_buffer_sequence`]
|
||||||
|
][
|
||||||
|
Determine if a type meets the requirements of __MutableBufferSequence__.
|
||||||
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.is_sync_read_stream `is_sync_read_stream`]
|
||||||
|
][
|
||||||
|
Determine if a type meets the requirements of __SyncReadStream__.
|
||||||
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.is_sync_stream `is_sync_stream`]
|
||||||
|
][
|
||||||
|
Determine if a type meets the requirements of both __SyncReadStream__
|
||||||
|
and __SyncWriteStream__.
|
||||||
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.is_sync_write_stream `is_sync_write_stream`]
|
||||||
|
][
|
||||||
|
Determine if a type meets the requirements of __SyncWriteStream__.
|
||||||
|
]]
|
||||||
|
]
|
||||||
|
|
||||||
|
[endsect]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[section:dynamic_buffer DynamicBuffer]
|
||||||
|
|
||||||
|
The networking technical specification described in __N4588__ provides a
|
||||||
|
concept called a __DynamicBuffer__. Instances of this concept define
|
||||||
|
an output area expressed as a __MutableBufferSequence__ and an input area
|
||||||
|
expressed as a __ConstBufferSequence__. Octets may be moved from the output
|
||||||
|
area to the input area through a structured interface, and later consumed
|
||||||
|
from the input area when the data is no longer needed. Beast adopts this
|
||||||
|
concept by providing a concise definition taken directly from the technical
|
||||||
|
specification and using it as the interface for operations which require
|
||||||
|
dynamically sized buffers. Several classes are provided which implement the
|
||||||
|
dynamic buffer concept using various strategies:
|
||||||
|
|
||||||
|
[table Dynamic buffer implementations
|
||||||
|
[[Name][Description]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.multi_buffer `multi_buffer`]
|
||||||
|
[link beast.ref.basic_multi_buffer `basic_multi_buffer`]
|
||||||
|
][
|
||||||
|
Uses a sequence of one or more character arrays of varying sizes.
|
||||||
|
Additional character array objects are appended to the sequence to
|
||||||
|
accommodate changes in the size of the character sequence. The basic
|
||||||
|
container supports the standard allocator model.
|
||||||
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.flat_buffer `flat_buffer`]
|
||||||
|
[link beast.ref.basic_flat_buffer `basic_flat_buffer`]
|
||||||
|
][
|
||||||
|
Guarantees that input and output areas are buffer sequences with
|
||||||
|
length one. Upon construction an optional upper limit to the total
|
||||||
|
size of the input and output areas may be set. The basic container
|
||||||
|
supports the standard allocator model.
|
||||||
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.static_buffer `static_buffer`]
|
||||||
|
[link beast.ref.static_buffer `static_buffer_n`]
|
||||||
|
][
|
||||||
|
Provides the facilities of a dynamic buffer, subject to an upper
|
||||||
|
limit placed on the total size of the input and output areas defined
|
||||||
|
by a constexpr template parameter. The storage for the sequences are
|
||||||
|
kept in the class; the implementation does not perform heap allocations.
|
||||||
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.buffers_adapter `buffers_adapter`]
|
||||||
|
][
|
||||||
|
This wrapper adapts any __MutableBufferSequence__ into a
|
||||||
|
__DynamicBuffer__ with an upper limit on the total size of the input and
|
||||||
|
output areas equal to the size of the underlying mutable buffer sequence.
|
||||||
|
The implementation does not perform heap allocations.
|
||||||
|
]]
|
||||||
|
]
|
||||||
|
|
||||||
|
[endsect]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[section:algorithms Buffer Algorithms]
|
||||||
|
|
||||||
|
Beast provides a collection of algorithms to work on __ConstBufferSequence__
|
||||||
|
or __MutableBufferSequence__ objects. These algorithms allow composition of
|
||||||
|
new algorithms which work on any objects meeting the buffer sequence
|
||||||
|
requirements, in an efficient way: no memory allocations are performed;
|
||||||
|
instead, the algorithms implement lightweight iterators over the existing
|
||||||
|
underlying memory, whose lifetime is retained by the caller.
|
||||||
|
|
||||||
|
[table Buffer algorithms
|
||||||
|
[[Name][Description]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.buffer_cat `buffer_cat`]
|
||||||
|
][
|
||||||
|
The functions returns a new buffer sequence which, when iterated,
|
||||||
|
traverses the sequence which would be formed if all of the input buffer
|
||||||
|
sequences were concatenated. This powerful function allows multiple calls
|
||||||
|
to a stream's `write_some` function to be combined into one, eliminating
|
||||||
|
expensive system calls.
|
||||||
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.consuming_buffers `consuming_buffers`]
|
||||||
|
][
|
||||||
|
This class wraps the underlying memory of an existing buffer sequence
|
||||||
|
and presents a suffix of the original sequence. The length of the suffix
|
||||||
|
may be progressively shortened. This lets callers work with sequential
|
||||||
|
increments of a buffer sequence.
|
||||||
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.prepare_buffer `prepare_buffer`]
|
||||||
|
[link beast.ref.prepare_buffers `prepare_buffers`]
|
||||||
|
][
|
||||||
|
These functions return a new buffer sequence which wraps the underlying
|
||||||
|
memory of an existing buffer sequence, but with a smaller size. This
|
||||||
|
lets callers work with a prefix of a buffer sequence.
|
||||||
|
]]
|
||||||
|
]
|
||||||
|
|
||||||
|
[endsect]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[section:async Asynchronous Model]
|
||||||
|
|
||||||
|
Asynchronous operations are started by calling a free function or member
|
||||||
|
function known as an ['asynchronous initiation function]. The initiation
|
||||||
|
function accepts parameters specific to the operation as well as a "completion
|
||||||
|
token." This token is either a completion handler, or another type allowing for
|
||||||
|
customization of how the result of the asynchronous operation is conveyed to
|
||||||
|
callers. Boost.Asio allows the special completion tokens __use_future__ and
|
||||||
|
objects of type __yield_context__ to allow callers to specify the use of futures
|
||||||
|
and coroutines respectively. This system, where the return value and method of
|
||||||
|
indicating completion may be customize at the call site of the asynchronous
|
||||||
|
initiation function, is known as the ['Extensible Asynchronous Model] described
|
||||||
|
in __N3747__, and built-in to __N4588__.
|
||||||
|
|
||||||
|
[note
|
||||||
|
A full explanation of completion handlers, the Extensible Asynchronous
|
||||||
|
Model and how Boost.Asio's asynchronous interfaces are used is beyond the
|
||||||
|
scope of this document. Readers should consult the Boost.Asio documentation
|
||||||
|
for a comprehensive treatment.
|
||||||
|
]
|
||||||
|
|
||||||
|
Since Beast is low level, authors of libraries may wish to create higher level
|
||||||
|
interfaces using the primitives found in this library. Non-trivial applications
|
||||||
|
will want to provide their own asychronous initiation functions which perform
|
||||||
|
a series of other, intermediate asynchronous operations before invoking the
|
||||||
|
final completion handler. The set of intermediate actions produced by calling
|
||||||
|
an initiation function is known as a ['composed operation]. To ensure full
|
||||||
|
interoperability and well-defined behavior, Boost.Asio imposes requirements on
|
||||||
|
the implementation of composed operations. Beast provides a number of useful
|
||||||
|
classes and macros to facilitate the development of composed operations and
|
||||||
|
the associated asynchronous initiation functions used to launch them.
|
||||||
|
|
||||||
|
[table Asynchronous Helpers
|
||||||
|
[[Name][Description]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.handler_type `handler_type`]
|
||||||
|
][
|
||||||
|
This template alias converts a completion token and signature to the
|
||||||
|
correct completion handler type. It is used in the implementation of
|
||||||
|
asynchronous initiation functions to meet the requirements of the
|
||||||
|
Extensible Asynchronous Model.
|
||||||
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.async_return_type `async_return_type`]
|
||||||
|
][
|
||||||
|
This template alias determines the return value of an asynchronous
|
||||||
|
initiation function given the completion token and signature. It is used
|
||||||
|
by asynchronous initiation functions to meet the requirements of the
|
||||||
|
Extensible Asynchronous Model.
|
||||||
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.async_completion `async_completion`]
|
||||||
|
][
|
||||||
|
This class aggregates the completion handler customization point and
|
||||||
|
the asynchronous initiation function return value customization point
|
||||||
|
into a single object which exposes the appropriate output types for the
|
||||||
|
given input types, and also contains boilerplate that is necessary to
|
||||||
|
implement an initiation function using the Extensible Model.
|
||||||
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.handler_alloc `handler_alloc`]
|
||||||
|
][
|
||||||
|
This class meets the requirements of [*Allocator], and uses any custom
|
||||||
|
memory allocation and deallocation hooks associated with a given handler.
|
||||||
|
It is useful for when a composed operation requires temporary dynamic
|
||||||
|
allocations to achieve its result. Memory allocated using this allocator
|
||||||
|
must be freed before the final completion handler is invoked.
|
||||||
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.handler_ptr `handler_ptr`]
|
||||||
|
][
|
||||||
|
This is a smart pointer container used to manage the internal state of a
|
||||||
|
composed operation. It is useful when the state is non trivial. For example
|
||||||
|
when the state has non-copyable or expensive to copy types. The container
|
||||||
|
takes ownership of the final completion handler, and provides boilerplate
|
||||||
|
to invoke the final handler in a way that also deletes the internal state.
|
||||||
|
The internal state is allocated using the final completion handler's
|
||||||
|
associated allocator, benefiting from all handler memory management
|
||||||
|
optimizations transparently.
|
||||||
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.bind_handler `bind_handler`]
|
||||||
|
][
|
||||||
|
This function returns a new, nullary completion handler which when
|
||||||
|
invoked with no arguments invokes the original completion handler with a
|
||||||
|
list of bound arguments. The invocation is made from the same implicit
|
||||||
|
or explicit strand as that which would be used to invoke the original
|
||||||
|
handler. This is accomplished by using the correct overload of
|
||||||
|
`asio_handler_invoke` associated with the original completion handler.
|
||||||
|
|
||||||
|
]]
|
||||||
|
]
|
||||||
|
|
||||||
|
When implementing composed operations it is necessary to provide hooks for
|
||||||
|
the composed operation which forward the hook calls to the hooks associated
|
||||||
|
with the final completion handler. These calls must be made from a namespace
|
||||||
|
that does not include overloads of the hook functions, since they depend on
|
||||||
|
argument dependent lookup to resolve. Beast provides a set of public helper
|
||||||
|
functions to invoke these hooks. These hooks are all located in the
|
||||||
|
`beast_asio_helpers` namespace rather than the `beast` namespace:
|
||||||
|
|
||||||
|
[table Handler Hooks
|
||||||
|
[[Name][Description]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.beast_asio_helpers__allocate `allocate`]
|
||||||
|
][
|
||||||
|
Allocation function for a handler. Asynchronous operations may need to
|
||||||
|
allocate temporary objects. Since asynchronous operations have a handler
|
||||||
|
function object, these temporary objects can be said to be associated with
|
||||||
|
the handler.
|
||||||
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.beast_asio_helpers__deallocate `deallocate`]
|
||||||
|
][
|
||||||
|
Deallocation function for a handler. The implementation guarantees that
|
||||||
|
the deallocation will occur before the associated handler is invoked, which
|
||||||
|
means the memory is ready to be reused for any new asynchronous operations
|
||||||
|
started by the handler.
|
||||||
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.beast_asio_helpers__invoke `invoke`]
|
||||||
|
][
|
||||||
|
Invocation function for a handler. When asynchronous operations are
|
||||||
|
composed from other asynchronous operations, all intermediate handlers
|
||||||
|
should be invoked using the same method as the final handler. This is
|
||||||
|
required to ensure that user-defined objects are not accessed in a way
|
||||||
|
that may violate the guarantees. This hooking function ensures that the
|
||||||
|
invoked method used for the final handler is accessible at each
|
||||||
|
intermediate step.
|
||||||
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.beast_asio_helpers__is_continuation `is_continuation`]
|
||||||
|
][
|
||||||
|
Continuation function for a handler. Asynchronous operations may represent
|
||||||
|
a continuation of the asynchronous control flow associated with the current
|
||||||
|
handler. The implementation can use this knowledge to optimise scheduling
|
||||||
|
of the handler.
|
||||||
|
]]
|
||||||
|
]
|
||||||
|
|
||||||
|
[endsect]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[section:tutorial Tutorial]
|
||||||
|
|
||||||
|
To illustrate the usage of the asynchronous helpers in the core section of
|
||||||
|
this library, we will develop a simple asynchronous composed operation called
|
||||||
|
[*echo]. This operation will read up to the first newline on a stream, and
|
||||||
|
then write the same line including the newline back on the stream.
|
||||||
|
|
||||||
|
First we define the input parameters and results, then declare our initiation
|
||||||
|
function. For our echo operation the only inputs are the stream and the
|
||||||
|
completion token. The output is the error code which is usually included in
|
||||||
|
all completion handler signatures.
|
||||||
|
|
||||||
|
```
|
||||||
|
#include <beast/core.hpp>
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
// Read a line and echo it back
|
||||||
|
//
|
||||||
|
template<class AsyncStream, class CompletionToken>
|
||||||
|
beast::async_return_type<CompletionToken, void(beast::error_code)>
|
||||||
|
async_echo(AsyncStream& stream, CompletionToken&& token)
|
||||||
|
```
|
||||||
|
|
||||||
|
Now that we have a declaration, we will define the body of the function. We
|
||||||
|
want to achieve the following goals: perform static type checking on the input
|
||||||
|
parameters, set up the return value as per __N3747__, and launch the composed
|
||||||
|
operation by constructing the object and invoking it.
|
||||||
|
|
||||||
|
```
|
||||||
|
template<class AsyncStream, class Handler>
|
||||||
|
class echo_op; // This is our composed operation implementation
|
||||||
|
|
||||||
|
// Read a line and echo it back
|
||||||
|
//
|
||||||
|
template<class AsyncStream, class CompletionToken>
|
||||||
|
beast::async_return_type<CompletionToken, void(beast::error_code)>
|
||||||
|
async_echo(AsyncStream& stream, CompletionToken&& token)
|
||||||
|
{
|
||||||
|
// Make sure stream meets the requirements. We use static_assert
|
||||||
|
// instead of letting the compiler generate several pages of hard
|
||||||
|
// to read error messages.
|
||||||
|
//
|
||||||
|
static_assert(beast::is_async_stream<AsyncStream>::value,
|
||||||
|
"AsyncStream requirements not met");
|
||||||
|
|
||||||
|
// This helper manages some of the handler's lifetime and
|
||||||
|
// uses the result and handler specializations associated with
|
||||||
|
// the completion token to help customize the return value.
|
||||||
|
//
|
||||||
|
beast::async_completion<CompletionToken, void(beast::error_code)> init{token};
|
||||||
|
|
||||||
|
// Create the composed operation and launch it. This is a constructor
|
||||||
|
// call followed by invocation of operator(). We use BEAST_HANDLER_TYPE
|
||||||
|
// to convert the completion token into the correct handler type,
|
||||||
|
// allowing user defined specializations of the async result template
|
||||||
|
// to take effect.
|
||||||
|
//
|
||||||
|
echo_op<AsyncStream, beast::handler_type<CompletionToken, void(beast::error_code)>>{
|
||||||
|
stream, init.completion_handler}(beast::error_code{}, 0);
|
||||||
|
|
||||||
|
// This hook lets the caller see a return value when appropriate.
|
||||||
|
// For example this might return std::future<error_code> if
|
||||||
|
// CompletionToken is boost::asio::use_future, or this might
|
||||||
|
// return an error code if CompletionToken specifies a coroutine.
|
||||||
|
//
|
||||||
|
return init.result.get();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The initiation function contains a few relatively simple parts. There is the
|
||||||
|
customization of the return value type, static type checking, building the
|
||||||
|
return value type using the helper, and creating and launching the composed
|
||||||
|
operation object. The [*`echo_op`] object does most of the work here, and has
|
||||||
|
a somewhat non-trivial structure. This structure is necessary to meet the
|
||||||
|
stringent requirements of composed operations (described in more detail in
|
||||||
|
the Boost.Asio documentation). We will touch on these requirements without
|
||||||
|
explaining them in depth.
|
||||||
|
|
||||||
|
First we will create boilerplate which is present in all composed operations
|
||||||
|
written in this style:
|
||||||
|
|
||||||
|
```
|
||||||
|
// This composed operation reads a line of input and echoes it back.
|
||||||
|
//
|
||||||
|
template<class AsyncStream, class Handler>
|
||||||
|
class echo_op
|
||||||
|
{
|
||||||
|
// This holds all of the state information required by the operation.
|
||||||
|
struct state
|
||||||
|
{
|
||||||
|
// The stream to read and write to
|
||||||
|
AsyncStream& stream;
|
||||||
|
|
||||||
|
// Indicates what step in the operation's state machine
|
||||||
|
// to perform next, starting from zero.
|
||||||
|
int step = 0;
|
||||||
|
|
||||||
|
// The buffer used to hold the input and output data.
|
||||||
|
// Note that we use a custom allocator for performance,
|
||||||
|
// this allows the implementation of the io_service to
|
||||||
|
// make efficient re-use of memory allocated by composed
|
||||||
|
// operations during continuations.
|
||||||
|
//
|
||||||
|
boost::asio::basic_streambuf<beast::handler_alloc<char, Handler>> buffer;
|
||||||
|
|
||||||
|
// handler_ptr requires that the first parameter to the
|
||||||
|
// contained object constructor is a reference to the
|
||||||
|
// managed final completion handler.
|
||||||
|
//
|
||||||
|
explicit state(Handler& handler, AsyncStream& stream_)
|
||||||
|
: stream(stream_)
|
||||||
|
, buffer((std::numeric_limits<std::size_t>::max)(),
|
||||||
|
beast::handler_alloc<char, Handler>{handler})
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// This smart pointer container allocates our state using the
|
||||||
|
// memory allocation hooks associated with the final completion
|
||||||
|
// handler, manages the lifetime of that handler for us, and
|
||||||
|
// enforces the destroy-before-invocation requirement on memory
|
||||||
|
// allocated using the hooks.
|
||||||
|
//
|
||||||
|
beast::handler_ptr<state, Handler> p_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Boost.Asio requires that handlers are CopyConstructible.
|
||||||
|
// In some cases, it takes advantage of handlers that are
|
||||||
|
// MoveConstructible. This operation supports both.
|
||||||
|
//
|
||||||
|
echo_op(echo_op&&) = default;
|
||||||
|
echo_op(echo_op const&) = default;
|
||||||
|
|
||||||
|
// The constructor simply creates our state variables in
|
||||||
|
// the smart pointer container.
|
||||||
|
//
|
||||||
|
template<class DeducedHandler, class... Args>
|
||||||
|
echo_op(AsyncStream& stream, DeducedHandler&& handler)
|
||||||
|
: p_(std::forward<DeducedHandler>(handler), stream)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determines if the next asynchronous operation represents a
|
||||||
|
// continuation of the asynchronous flow of control associated
|
||||||
|
// with the final handler. If we are past step one, it means
|
||||||
|
// we have performed an asynchronous operation therefore any
|
||||||
|
// subsequent operation would represent a continuation.
|
||||||
|
// Otherwise, we propagate the handler's associated value of
|
||||||
|
// is_continuation. Getting this right means the implementation
|
||||||
|
// may schedule the invokation of the invoked functions more
|
||||||
|
// efficiently.
|
||||||
|
//
|
||||||
|
friend bool asio_handler_is_continuation(echo_op* op)
|
||||||
|
{
|
||||||
|
// This next call is structured to permit argument
|
||||||
|
// dependent lookup to take effect.
|
||||||
|
using boost::asio::asio_handler_is_continuation;
|
||||||
|
|
||||||
|
// Always use std::addressof to pass the pointer to the handler,
|
||||||
|
// otherwise an unwanted overload of operator& may be called instead.
|
||||||
|
return op->p_->step > 1 ||
|
||||||
|
asio_handler_is_continuation(std::addressof(op->p_.handler()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handler hook forwarding. These free functions invoke the hooks
|
||||||
|
// associated with the final completion handler. In effect, they
|
||||||
|
// make the Asio implementation treat our composed operation the
|
||||||
|
// same way it would treat the final completion handler for the
|
||||||
|
// purpose of memory allocation and invocation.
|
||||||
|
//
|
||||||
|
// Our implementation just passes through the call to the hook
|
||||||
|
// associated with the final handler.
|
||||||
|
|
||||||
|
friend void* asio_handler_allocate(std::size_t size, echo_op* op)
|
||||||
|
{
|
||||||
|
using boost::asio::asio_handler_allocate;
|
||||||
|
return asio_handler_allocate(size, std::addressof(op->p_.handler()));
|
||||||
|
}
|
||||||
|
|
||||||
|
friend void asio_handler_deallocate(void* p, std::size_t size, echo_op* op)
|
||||||
|
{
|
||||||
|
using boost::asio::asio_handler_deallocate;
|
||||||
|
return asio_handler_deallocate(p, size, std::addressof(op->p_.handler()));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Function>
|
||||||
|
friend void asio_handler_invoke(Function&& f, echo_op* op)
|
||||||
|
{
|
||||||
|
using boost::asio::asio_handler_invoke;
|
||||||
|
return asio_handler_invoke(f, std::addressof(op->p_.handler()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Our main entry point. This will get called as our
|
||||||
|
// intermediate operations complete. Definition below.
|
||||||
|
//
|
||||||
|
void operator()(beast::error_code ec, std::size_t bytes_transferred);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
We have the common boilerplate for a composed operation and now we just need
|
||||||
|
to implement the function call operator. Our strategy is to make our composed
|
||||||
|
object meet the requirements of a completion handler by being copyable (also
|
||||||
|
movable), and by providing the function call operator with the correct
|
||||||
|
signature. Rather than using `std::bind` or `boost::bind`, which destroys
|
||||||
|
the type information and therefore breaks the allocation and invocation
|
||||||
|
hooks, we will simply pass `std::move(*this)` as the completion handler
|
||||||
|
parameter for any operations that we initiate. For the move to work correctly,
|
||||||
|
care must be taken to ensure that no access to data members are made after the
|
||||||
|
move takes place. Here is the implementation of the function call operator for
|
||||||
|
this echo operation:
|
||||||
|
```
|
||||||
|
// We are callable with the signature void(error_code, bytes_transferred),
|
||||||
|
// allowing `*this` to be used as both a ReadHandler and a WriteHandler.
|
||||||
|
//
|
||||||
|
template<class AsyncStream, class Handler>
|
||||||
|
void echo_op<AsyncStream, Handler>::
|
||||||
|
operator()(beast::error_code ec, std::size_t bytes_transferred)
|
||||||
|
{
|
||||||
|
// Store a reference to our state. The address of the state won't
|
||||||
|
// change, and this solves the problem where dereferencing the
|
||||||
|
// data member is undefined after a move.
|
||||||
|
auto& p = *p_;
|
||||||
|
|
||||||
|
// Now perform the next step in the state machine
|
||||||
|
switch(ec ? 2 : p.step)
|
||||||
|
{
|
||||||
|
// initial entry
|
||||||
|
case 0:
|
||||||
|
// read up to the first newline
|
||||||
|
p.step = 1;
|
||||||
|
return boost::asio::async_read_until(p.stream, p.buffer, "\n", std::move(*this));
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
// write everything back
|
||||||
|
p.step = 2;
|
||||||
|
return boost::asio::async_write(p.stream, p.buffer.data(), std::move(*this));
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invoke the final handler. If we wanted to pass any arguments
|
||||||
|
// which come from our state, they would have to be moved to the
|
||||||
|
// stack first, since the `handler_ptr` guarantees that the state
|
||||||
|
// is destroyed before
|
||||||
|
// the handler is invoked.
|
||||||
|
//
|
||||||
|
p_.invoke(ec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
A complete, runnable version of this example may be found in the examples
|
||||||
|
directory.
|
||||||
|
|
||||||
|
[endsect]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[endsect]
|
@@ -486,7 +486,7 @@ start. Other design goals:
|
|||||||
Beast doesn't allocate or make copies of buffers when sending data. The
|
Beast doesn't allocate or make copies of buffers when sending data. The
|
||||||
caller's buffers are sent in-place. You can use any object meeting the
|
caller's buffers are sent in-place. You can use any object meeting the
|
||||||
requirements of
|
requirements of
|
||||||
[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/ConstBufferSequence.html ConstBufferSequence],
|
[@http://www.boost.org/doc/html/boost_asio/reference/ConstBufferSequence.html ConstBufferSequence],
|
||||||
permitting efficient scatter-gather I/O.
|
permitting efficient scatter-gather I/O.
|
||||||
|
|
||||||
The [*ConstBufferSequence] interface allows callers to send data from
|
The [*ConstBufferSequence] interface allows callers to send data from
|
||||||
@@ -588,8 +588,8 @@ start. Other design goals:
|
|||||||
|
|
||||||
[table
|
[table
|
||||||
[
|
[
|
||||||
[[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/async_connect.html Beast],
|
[[@http://www.boost.org/doc/html/boost_asio/reference/async_connect.html Beast],
|
||||||
[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/basic_socket_acceptor/async_accept.html also]]
|
[@http://www.boost.org/doc/html/boost_asio/reference/basic_socket_acceptor/async_accept.html also]]
|
||||||
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/asio/endpoint.hpp#L52 websocketpp]]
|
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/asio/endpoint.hpp#L52 websocketpp]]
|
||||||
][
|
][
|
||||||
[```
|
[```
|
||||||
|
@@ -127,6 +127,15 @@ type, in `file_body`.
|
|||||||
* [@examples/http_sync_server.hpp]
|
* [@examples/http_sync_server.hpp]
|
||||||
* [@examples/http_server.cpp]
|
* [@examples/http_server.cpp]
|
||||||
|
|
||||||
|
[heading Composed Operations]
|
||||||
|
|
||||||
|
This program shows how to use Beast's core foundations to build a
|
||||||
|
composable asynchronous initiation function with associated composed
|
||||||
|
operation implementation. This is a complete, runnable version of
|
||||||
|
the example described in the Core Foundations document section.
|
||||||
|
|
||||||
|
* [@examples/echo_op.cpp]
|
||||||
|
|
||||||
[heading Listings]
|
[heading Listings]
|
||||||
|
|
||||||
These are stand-alone listings of the HTTP and WebSocket examples.
|
These are stand-alone listings of the HTTP and WebSocket examples.
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 39 KiB |
@@ -23,22 +23,25 @@
|
|||||||
[template indexterm1[term1] '''<indexterm><primary>'''[term1]'''</primary></indexterm>''']
|
[template indexterm1[term1] '''<indexterm><primary>'''[term1]'''</primary></indexterm>''']
|
||||||
[template indexterm2[term1 term2] '''<indexterm><primary>'''[term1]'''</primary><secondary>'''[term2]'''</secondary></indexterm>''']
|
[template indexterm2[term1 term2] '''<indexterm><primary>'''[term1]'''</primary><secondary>'''[term2]'''</secondary></indexterm>''']
|
||||||
|
|
||||||
|
[def __N3747__ [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3747.pdf [*N3747]]]
|
||||||
[def __N4588__ [@http://cplusplus.github.io/networking-ts/draft.pdf [*N4588]]]
|
[def __N4588__ [@http://cplusplus.github.io/networking-ts/draft.pdf [*N4588]]]
|
||||||
[def __rfc6455__ [@https://tools.ietf.org/html/rfc6455 rfc6455]]
|
[def __rfc6455__ [@https://tools.ietf.org/html/rfc6455 rfc6455]]
|
||||||
[def __rfc7230__ [@https://tools.ietf.org/html/rfc7230 rfc7230]]
|
[def __rfc7230__ [@https://tools.ietf.org/html/rfc7230 rfc7230]]
|
||||||
|
|
||||||
[def __asio_handler_invoke__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/asio_handler_invoke.html `asio_handler_invoke`]]
|
[def __asio_handler_invoke__ [@http://www.boost.org/doc/html/boost_asio/reference/asio_handler_invoke.html `asio_handler_invoke`]]
|
||||||
[def __asio_handler_allocate__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/asio_handler_allocate.html `asio_handler_allocate`]]
|
[def __asio_handler_allocate__ [@http://www.boost.org/doc/html/boost_asio/reference/asio_handler_allocate.html `asio_handler_allocate`]]
|
||||||
[def __void_or_deduced__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/asynchronous_operations.html#boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]]
|
[def __void_or_deduced__ [@http://www.boost.org/doc/html/boost_asio/reference/asynchronous_operations.html#boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]]
|
||||||
|
[def __use_future__ [@http://www.boost.org/doc/html/boost_asio/reference/use_future_t.html `boost::asio::use_future`]]
|
||||||
|
[def __yield_context__ [@http://www.boost.org/doc/html/boost_asio/reference/yield_context.html `boost::asio::yield_context`]]
|
||||||
|
|
||||||
[def __AsyncReadStream__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/AsyncReadStream.html [*AsyncReadStream]]]
|
[def __AsyncReadStream__ [@http://www.boost.org/doc/html/boost_asio/reference/AsyncReadStream.html [*AsyncReadStream]]]
|
||||||
[def __AsyncWriteStream__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/AsyncWriteStream.html [*AsyncWriteStream]]]
|
[def __AsyncWriteStream__ [@http://www.boost.org/doc/html/boost_asio/reference/AsyncWriteStream.html [*AsyncWriteStream]]]
|
||||||
[def __CompletionHandler__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/CompletionHandler.html [*CompletionHandler]]]
|
[def __CompletionHandler__ [@http://www.boost.org/doc/html/boost_asio/reference/CompletionHandler.html [*CompletionHandler]]]
|
||||||
[def __ConstBufferSequence__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/ConstBufferSequence.html [*ConstBufferSequence]]]
|
[def __ConstBufferSequence__ [@http://www.boost.org/doc/html/boost_asio/reference/ConstBufferSequence.html [*ConstBufferSequence]]]
|
||||||
[def __Handler__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/Handler.html [*Handler]]]
|
[def __Handler__ [@http://www.boost.org/doc/html/boost_asio/reference/Handler.html [*Handler]]]
|
||||||
[def __MutableBufferSequence__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/MutableBufferSequence.html [*MutableBufferSequence]]]
|
[def __MutableBufferSequence__ [@http://www.boost.org/doc/html/boost_asio/reference/MutableBufferSequence.html [*MutableBufferSequence]]]
|
||||||
[def __SyncReadStream__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/SyncReadStream.html [*SyncReadStream]]]
|
[def __SyncReadStream__ [@http://www.boost.org/doc/html/boost_asio/reference/SyncReadStream.html [*SyncReadStream]]]
|
||||||
[def __SyncWriteStream__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/SyncWriteStream.html [*SyncWriteStream]]]
|
[def __SyncWriteStream__ [@http://www.boost.org/doc/html/boost_asio/reference/SyncWriteStream.html [*SyncWriteStream]]]
|
||||||
|
|
||||||
[def __Body__ [link beast.ref.Body [*`Body`]]]
|
[def __Body__ [link beast.ref.Body [*`Body`]]]
|
||||||
[def __DynamicBuffer__ [link beast.ref.DynamicBuffer [*DynamicBuffer]]]
|
[def __DynamicBuffer__ [link beast.ref.DynamicBuffer [*DynamicBuffer]]]
|
||||||
@@ -62,6 +65,11 @@ provides implementations of the HTTP and WebSocket protocols.
|
|||||||
][
|
][
|
||||||
An introduction with features, requirements, and credits.
|
An introduction with features, requirements, and credits.
|
||||||
]]
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.core Core Concepts]
|
||||||
|
][
|
||||||
|
Library-wide concepts, classes, functions, and traits.
|
||||||
|
]]
|
||||||
[[
|
[[
|
||||||
[link beast.http Using HTTP]
|
[link beast.http Using HTTP]
|
||||||
][
|
][
|
||||||
@@ -96,6 +104,7 @@ provides implementations of the HTTP and WebSocket protocols.
|
|||||||
]
|
]
|
||||||
|
|
||||||
[include overview.qbk]
|
[include overview.qbk]
|
||||||
|
[include core.qbk]
|
||||||
[include http.qbk]
|
[include http.qbk]
|
||||||
[include websocket.qbk]
|
[include websocket.qbk]
|
||||||
[include examples.qbk]
|
[include examples.qbk]
|
||||||
|
@@ -43,7 +43,7 @@ Beast requires:
|
|||||||
* [*Boost.] Beast is built on Boost, especially Boost.Asio.
|
* [*Boost.] Beast is built on Boost, especially Boost.Asio.
|
||||||
* [*OpenSSL.] If using TLS/Secure sockets (optional).
|
* [*OpenSSL.] If using TLS/Secure sockets (optional).
|
||||||
|
|
||||||
[note Tested compilers: msvc-14+, gcc 5+, clang 3.6+]
|
[note Tested compilers: msvc-14+, gcc 4.8+, clang 3.6+]
|
||||||
|
|
||||||
The library is [*header-only]. It is not necessary to add any .cpp files,
|
The library is [*header-only]. It is not necessary to add any .cpp files,
|
||||||
or to add commands to your build script for building Beast. To link your
|
or to add commands to your build script for building Beast. To link your
|
||||||
|
@@ -29,7 +29,7 @@
|
|||||||
<entry valign="top">
|
<entry valign="top">
|
||||||
<bridgehead renderas="sect3">Classes</bridgehead>
|
<bridgehead renderas="sect3">Classes</bridgehead>
|
||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
<member><link linkend="beast.ref.http__basic_dynamic_body">http__basic_dynamic_body</link></member>
|
<member><link linkend="beast.ref.http__basic_dynamic_body">basic_dynamic_body</link></member>
|
||||||
<member><link linkend="beast.ref.http__basic_fields">basic_fields</link></member>
|
<member><link linkend="beast.ref.http__basic_fields">basic_fields</link></member>
|
||||||
<member><link linkend="beast.ref.http__basic_parser">basic_parser</link></member>
|
<member><link linkend="beast.ref.http__basic_parser">basic_parser</link></member>
|
||||||
<member><link linkend="beast.ref.http__dynamic_body">dynamic_body</link></member>
|
<member><link linkend="beast.ref.http__dynamic_body">dynamic_body</link></member>
|
||||||
@@ -159,7 +159,6 @@
|
|||||||
<member><link linkend="beast.ref.buffers_adapter">buffers_adapter</link></member>
|
<member><link linkend="beast.ref.buffers_adapter">buffers_adapter</link></member>
|
||||||
<member><link linkend="beast.ref.consuming_buffers">consuming_buffers</link></member>
|
<member><link linkend="beast.ref.consuming_buffers">consuming_buffers</link></member>
|
||||||
<member><link linkend="beast.ref.buffered_read_stream">buffered_read_stream</link></member>
|
<member><link linkend="beast.ref.buffered_read_stream">buffered_read_stream</link></member>
|
||||||
<member><link linkend="beast.ref.errc">errc</link></member>
|
|
||||||
<member><link linkend="beast.ref.error_category">error_category</link></member>
|
<member><link linkend="beast.ref.error_category">error_category</link></member>
|
||||||
<member><link linkend="beast.ref.error_code">error_code</link></member>
|
<member><link linkend="beast.ref.error_code">error_code</link></member>
|
||||||
<member><link linkend="beast.ref.error_condition">error_condition</link></member>
|
<member><link linkend="beast.ref.error_condition">error_condition</link></member>
|
||||||
@@ -187,23 +186,35 @@
|
|||||||
<member><link linkend="beast.ref.system_category">system_category</link></member>
|
<member><link linkend="beast.ref.system_category">system_category</link></member>
|
||||||
<member><link linkend="beast.ref.to_static_string">to_static_string</link></member>
|
<member><link linkend="beast.ref.to_static_string">to_static_string</link></member>
|
||||||
</simplelist>
|
</simplelist>
|
||||||
|
<bridgehead renderas="sect3">Constants</bridgehead>
|
||||||
|
<simplelist type="vert" columns="1">
|
||||||
|
<member><link linkend="beast.ref.errc">errc</link></member>
|
||||||
|
</simplelist>
|
||||||
</entry>
|
</entry>
|
||||||
<entry valign="top">
|
<entry valign="top">
|
||||||
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
<member><link linkend="beast.ref.is_AsyncReadStream">is_AsyncReadStream</link></member>
|
<member><link linkend="beast.ref.has_get_io_service">has_get_io_service</link></member>
|
||||||
<member><link linkend="beast.ref.is_AsyncWriteStream">is_AsyncWriteStream</link></member>
|
<member><link linkend="beast.ref.is_async_read_stream">is_async_read_stream</link></member>
|
||||||
<member><link linkend="beast.ref.is_AsyncStream">is_AsyncStream</link></member>
|
<member><link linkend="beast.ref.is_async_write_stream">is_async_write_stream</link></member>
|
||||||
<member><link linkend="beast.ref.is_CompletionHandler">is_CompletionHandler</link></member>
|
<member><link linkend="beast.ref.is_async_stream">is_async_stream</link></member>
|
||||||
|
<member><link linkend="beast.ref.is_completion_handler">is_completion_handler</link></member>
|
||||||
<member><link linkend="beast.ref.is_const_buffer_sequence">is_const_buffer_sequence</link></member>
|
<member><link linkend="beast.ref.is_const_buffer_sequence">is_const_buffer_sequence</link></member>
|
||||||
<member><link linkend="beast.ref.is_dynamic_buffer">is_dynamic_buffer</link></member>
|
<member><link linkend="beast.ref.is_dynamic_buffer">is_dynamic_buffer</link></member>
|
||||||
<member><link linkend="beast.ref.is_mutable_buffer_sequence">is_mutable_buffer_sequence</link></member>
|
<member><link linkend="beast.ref.is_mutable_buffer_sequence">is_mutable_buffer_sequence</link></member>
|
||||||
<member><link linkend="beast.ref.is_SyncReadStream">is_SyncReadStream</link></member>
|
<member><link linkend="beast.ref.is_sync_read_stream">is_sync_read_stream</link></member>
|
||||||
<member><link linkend="beast.ref.is_SyncStream">is_SyncStream</link></member>
|
<member><link linkend="beast.ref.is_sync_stream">is_sync_stream</link></member>
|
||||||
<member><link linkend="beast.ref.is_SyncWriteStream">is_SyncWriteStream</link></member>
|
<member><link linkend="beast.ref.is_sync_write_stream">is_sync_write_stream</link></member>
|
||||||
</simplelist>
|
</simplelist>
|
||||||
</entry>
|
</entry>
|
||||||
<entry valign="top">
|
<entry valign="top">
|
||||||
|
<bridgehead renderas="sect3">Helpers</bridgehead>
|
||||||
|
<simplelist type="vert" columns="1">
|
||||||
|
<member><link linkend="beast.ref.beast_asio_helpers__allocate">allocate</link></member>
|
||||||
|
<member><link linkend="beast.ref.beast_asio_helpers__deallocate">deallocate</link></member>
|
||||||
|
<member><link linkend="beast.ref.beast_asio_helpers__invoke">invoke</link></member>
|
||||||
|
<member><link linkend="beast.ref.beast_asio_helpers__is_continuation">is_continuation</link></member>
|
||||||
|
</simplelist>
|
||||||
<bridgehead renderas="sect3">Concepts</bridgehead>
|
<bridgehead renderas="sect3">Concepts</bridgehead>
|
||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
<member><link linkend="beast.ref.streams.AsyncStream">AsyncStream</link></member>
|
<member><link linkend="beast.ref.streams.AsyncStream">AsyncStream</link></member>
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
A `BufferSequence` is a type meeting either of the following requirements:
|
A `BufferSequence` is a type meeting either of the following requirements:
|
||||||
|
|
||||||
* [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/ConstBufferSequence.html [*`ConstBufferSequence`]]
|
* __ConstBufferSequence__
|
||||||
* [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/MutableBufferSequence.html [*`MutableBufferSequence`]]
|
* __MutableBufferSequence__
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
@@ -37,8 +37,8 @@ In the table below:
|
|||||||
* `a` denotes a value of type `X`.
|
* `a` denotes a value of type `X`.
|
||||||
* `c` denotes a (possibly const) value of type `X`.
|
* `c` denotes a (possibly const) value of type `X`.
|
||||||
* `n` denotes a value of type `std::size_t`.
|
* `n` denotes a value of type `std::size_t`.
|
||||||
* `T` denotes a type meeting the requirements for [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/ConstBufferSequence.html `ConstBufferSequence`].
|
* `T` denotes a type meeting the requirements for __ConstBufferSequence__.
|
||||||
* `U` denotes a type meeting the requirements for [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/MutableBufferSequence.html `MutableBufferSequence`].
|
* `U` denotes a type meeting the requirements for __MutableBufferSequence__.
|
||||||
|
|
||||||
[table DynamicBuffer requirements
|
[table DynamicBuffer requirements
|
||||||
[[operation] [type] [semantics, pre/post-conditions]]
|
[[operation] [type] [semantics, pre/post-conditions]]
|
||||||
|
@@ -21,14 +21,14 @@ A type modeling [*`Stream`] meets either or both of the following requirements:
|
|||||||
|
|
||||||
A type modeling [*`AsyncStream`] meets the following requirements:
|
A type modeling [*`AsyncStream`] meets the following requirements:
|
||||||
|
|
||||||
* [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/AsyncReadStream.html [*`AsyncReadStream`]]
|
* __AsyncReadStream__
|
||||||
* [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/AsyncWriteStream.html [*`AsyncWriteStream`]]
|
* __AsyncWriteStream__
|
||||||
|
|
||||||
[heading:SyncStream SyncStream]
|
[heading:SyncStream SyncStream]
|
||||||
|
|
||||||
A type modeling [*`SyncStream`] meets the following requirements:
|
A type modeling [*`SyncStream`] meets the following requirements:
|
||||||
|
|
||||||
* [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/SyncReadStream.html [*`SyncReadStream`]]
|
* __SyncReadStream__
|
||||||
* [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/SyncWriteStream.html [*`SyncWriteStream`]]
|
* __SyncWriteStream__
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
@@ -12,13 +12,10 @@
|
|||||||
<member><link linkend="beast.websocket.creation">Creation</link></member>
|
<member><link linkend="beast.websocket.creation">Creation</link></member>
|
||||||
<member><link linkend="beast.websocket.connections">Making connections</link></member>
|
<member><link linkend="beast.websocket.connections">Making connections</link></member>
|
||||||
<member><link linkend="beast.websocket.handshaking">Handshaking</link></member>
|
<member><link linkend="beast.websocket.handshaking">Handshaking</link></member>
|
||||||
|
<member><link linkend="beast.websocket.accepting">Accepting</link></member>
|
||||||
<member><link linkend="beast.websocket.messages">Messages</link></member>
|
<member><link linkend="beast.websocket.messages">Messages</link></member>
|
||||||
<member><link linkend="beast.websocket.frames">Frames</link></member>
|
|
||||||
<member><link linkend="beast.websocket.control">Control Frames</link></member>
|
<member><link linkend="beast.websocket.control">Control Frames</link></member>
|
||||||
<member><link linkend="beast.websocket.buffers">Buffers</link></member>
|
<member><link linkend="beast.websocket.notes">Notes</link></member>
|
||||||
<member><link linkend="beast.websocket.async">Asynchronous interface</link></member>
|
|
||||||
<member><link linkend="beast.websocket.io_service">The io_service</link></member>
|
|
||||||
<member><link linkend="beast.websocket.threads">Thread Safety</link></member>
|
|
||||||
</simplelist></entry></row></tbody></tgroup></informaltable>
|
</simplelist></entry></row></tbody></tgroup></informaltable>
|
||||||
''']
|
''']
|
||||||
|
|
||||||
@@ -30,9 +27,8 @@ this technology is to provide a mechanism for browser-based applications that
|
|||||||
need two-way communication with servers that does not rely on opening multiple
|
need two-way communication with servers that does not rely on opening multiple
|
||||||
HTTP connections.
|
HTTP connections.
|
||||||
|
|
||||||
Beast.WebSocket provides developers with a robust WebSocket implementation
|
Beast provides developers with a robust WebSocket implementation built on
|
||||||
built on Boost.Asio with a consistent asynchronous model using a modern
|
Boost.Asio with a consistent asynchronous model using a modern C++ approach.
|
||||||
C++ approach.
|
|
||||||
|
|
||||||
The WebSocket protocol is described fully in
|
The WebSocket protocol is described fully in
|
||||||
[@https://tools.ietf.org/html/rfc6455 rfc6455]
|
[@https://tools.ietf.org/html/rfc6455 rfc6455]
|
||||||
@@ -48,11 +44,11 @@ The WebSocket protocol is described fully in
|
|||||||
[section:creation Creation]
|
[section:creation Creation]
|
||||||
|
|
||||||
The interface to Beast's WebSocket implementation is a single template
|
The interface to Beast's WebSocket implementation is a single template
|
||||||
class [link beast.ref.websocket__stream `beast::websocket::stream`] which
|
class [link beast.ref.websocket__stream `websocket::stream`] which
|
||||||
wraps a "next layer" object. The next layer object must meet the requirements
|
wraps a "next layer" object. The next layer object must meet the requirements
|
||||||
of [link beast.ref.streams.SyncStream [*`SyncStream`]] if synchronous
|
of [link beast.ref.streams.SyncStream [*SyncStream]] if synchronous
|
||||||
operations are performed, or
|
operations are performed, or
|
||||||
[link beast.ref.streams.AsyncStream [*`AsyncStream`]] if asynchronous
|
[link beast.ref.streams.AsyncStream [*AsyncStream]] if asynchronous
|
||||||
operations are performed, or both. Arguments supplied during construction are
|
operations are performed, or both. Arguments supplied during construction are
|
||||||
passed to next layer's constructor. Here we declare a websocket stream over
|
passed to next layer's constructor. Here we declare a websocket stream over
|
||||||
a TCP/IP socket with ownership of the socket:
|
a TCP/IP socket with ownership of the socket:
|
||||||
@@ -85,7 +81,7 @@ beast::websocket::stream<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>
|
|||||||
For servers that can handshake in multiple protocols, it may be desired
|
For servers that can handshake in multiple protocols, it may be desired
|
||||||
to wrap an object that already exists. This socket can be moved in:
|
to wrap an object that already exists. This socket can be moved in:
|
||||||
```
|
```
|
||||||
boost::asio::ip::tcp::socket&& sock;
|
boost::asio::ip::tcp::socket sock;
|
||||||
...
|
...
|
||||||
beast::websocket::stream<boost::asio::ip::tcp::socket> ws{std::move(sock)};
|
beast::websocket::stream<boost::asio::ip::tcp::socket> ws{std::move(sock)};
|
||||||
```
|
```
|
||||||
@@ -140,6 +136,22 @@ void do_accept(boost::asio::ip::tcp::acceptor& acceptor)
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
When using SSL, which itself wraps a next layer object that is usualy a
|
||||||
|
TCP/IP socket, multiple calls to retrieve the next layer may be required:
|
||||||
|
```
|
||||||
|
beast::websocket::stream<boost::asio::ssl::stream<
|
||||||
|
boost::asio::ip::tcp::socket>> ws{ios, ctx};
|
||||||
|
|
||||||
|
// connect the underlying TCP/IP socket
|
||||||
|
ws.next_layer().next_layer().connect(ep);
|
||||||
|
|
||||||
|
// perform SSL handshake
|
||||||
|
ws.next_layer().handshake(boost::asio::ssl::stream_base::client);
|
||||||
|
|
||||||
|
// perform WebSocket handshake
|
||||||
|
ws.handshake("localhost", "/");
|
||||||
|
```
|
||||||
|
|
||||||
[note
|
[note
|
||||||
Examples use synchronous interfaces for clarity of exposition.
|
Examples use synchronous interfaces for clarity of exposition.
|
||||||
]
|
]
|
||||||
@@ -154,17 +166,103 @@ A WebSocket session begins when one side sends the HTTP Upgrade request
|
|||||||
for websocket, and the other side sends an appropriate HTTP response
|
for websocket, and the other side sends an appropriate HTTP response
|
||||||
indicating that the request was accepted and that the connection has
|
indicating that the request was accepted and that the connection has
|
||||||
been upgraded. The HTTP Upgrade request must include the Host HTTP field,
|
been upgraded. The HTTP Upgrade request must include the Host HTTP field,
|
||||||
and the URI of the resource to request.
|
and the target of the resource to request. The stream member functions
|
||||||
[link beast.ref.websocket__stream.handshake `handshake`] is used to send the
|
[link beast.ref.websocket__stream.handshake `handshake`] and
|
||||||
request with the required host and resource strings.
|
[link beast.ref.websocket__stream.async_handshake `async_handshake`]
|
||||||
|
are used to send the request with the required host and target strings.
|
||||||
```
|
```
|
||||||
beast::websocket::stream<boost::asio::ip::tcp::socket> ws{ios};
|
beast::websocket::stream<boost::asio::ip::tcp::socket> ws{ios};
|
||||||
...
|
...
|
||||||
ws.set_option(beast::websocket::keep_alive(true));
|
ws.set_option(beast::websocket::keep_alive(true));
|
||||||
ws.handshake("ws.example.com:80", "/cgi-bin/bitcoin-prices");
|
ws.handshake("localhost", "/");
|
||||||
```
|
```
|
||||||
|
|
||||||
The [link beast.ref.websocket__stream `stream`] automatically
|
The implementation will create and send an HTTP request that typically
|
||||||
|
looks like this:
|
||||||
|
|
||||||
|
[table WebSocket Upgrade HTTP Request
|
||||||
|
[[Serialized Octets][Description]]
|
||||||
|
[[
|
||||||
|
```
|
||||||
|
GET / HTTP/1.1
|
||||||
|
Host: localhost
|
||||||
|
Upgrade: websocket
|
||||||
|
Connection: upgrade
|
||||||
|
Sec-WebSocket-Key: 2pGeTR0DsE4dfZs2pH+8MA==
|
||||||
|
Sec-WebSocket-Version: 13
|
||||||
|
User-Agent: Beast
|
||||||
|
```
|
||||||
|
][
|
||||||
|
The host and target parameters become part of the Host field
|
||||||
|
and request-target in the resulting HTTP request. The key is
|
||||||
|
generated by the implementation. Callers may add fields or
|
||||||
|
modify fields by providing a ['decorator], described below.
|
||||||
|
]]]
|
||||||
|
|
||||||
|
[heading Decorators]
|
||||||
|
|
||||||
|
If the caller wishes to add or modify fields, the member functions
|
||||||
|
[link beast.ref.websocket__stream.handshake_ex `handshake_ex`] and
|
||||||
|
[link beast.ref.websocket__stream.async_handshake_ex `async_handshake_ex`]
|
||||||
|
are provided which allow an additional function object, called a
|
||||||
|
['decorator], to be passed. The decorator is invoked to modify
|
||||||
|
the HTTP Upgrade request as needed. This example sets a subprotocol
|
||||||
|
on the request:
|
||||||
|
```
|
||||||
|
void decorate(beast::websocket::request_type& req)
|
||||||
|
{
|
||||||
|
req.fields.insert("Sec-WebSocket-Protocol", "xmpp;ws-chat");
|
||||||
|
}
|
||||||
|
...
|
||||||
|
ws.handshake_ex("localhost", "/", &decorate);
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
The HTTP Upgrade request produced by the previous call will look thusly:
|
||||||
|
|
||||||
|
[table Decorated WebSocket Upgrade HTTP Request
|
||||||
|
[[Serialized Octets][Description]]
|
||||||
|
[[
|
||||||
|
```
|
||||||
|
GET / HTTP/1.1
|
||||||
|
Host: localhost
|
||||||
|
Upgrade: websocket
|
||||||
|
Connection: upgrade
|
||||||
|
Sec-WebSocket-Key: 2pGeTR0DsE4dfZs2pH+8MA==
|
||||||
|
Sec-WebSocket-Version: 13
|
||||||
|
Sec-WebSocket-Protocol: xmpp;ws-chat
|
||||||
|
User-Agent: Beast
|
||||||
|
```
|
||||||
|
][
|
||||||
|
Undefined behavior results if the decorator modifies the fields
|
||||||
|
specific to perform the WebSocket Upgrade , such as the Upgrade
|
||||||
|
and Connection fields.
|
||||||
|
]]]
|
||||||
|
|
||||||
|
[heading Filtering]
|
||||||
|
|
||||||
|
When a client receives an HTTP Upgrade response from the server indicating
|
||||||
|
a successful upgrade, the caller may wish to perform additional validation
|
||||||
|
on the received HTTP response message. For example, to check that the
|
||||||
|
response to a basic authentication challenge is valid. To achieve this,
|
||||||
|
overloads of the handshake member function allow the caller to store the
|
||||||
|
received HTTP message in an output reference argument as
|
||||||
|
[link beast.ref.websocket__response_type `response_type`]
|
||||||
|
as follows:
|
||||||
|
```
|
||||||
|
beast::websocket::response_type res;
|
||||||
|
ws.handshake(res, "localhost", "/");
|
||||||
|
if(! res.fields.exists("Sec-WebSocket-Protocol"))
|
||||||
|
throw std::invalid_argument("missing subprotocols");
|
||||||
|
```
|
||||||
|
|
||||||
|
[endsect]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[section:accepting Accepting]
|
||||||
|
|
||||||
|
A [link beast.ref.websocket__stream `stream`] automatically
|
||||||
handles receiving and processing the HTTP response to the handshake request.
|
handles receiving and processing the HTTP response to the handshake request.
|
||||||
The call to handshake is successful if a HTTP response is received with the
|
The call to handshake is successful if a HTTP response is received with the
|
||||||
101 "Switching Protocols" status code. On failure, an error is returned or an
|
101 "Switching Protocols" status code. On failure, an error is returned or an
|
||||||
@@ -179,10 +277,113 @@ similarly. If the handshake fails, an error is returned or exception thrown:
|
|||||||
ws.accept();
|
ws.accept();
|
||||||
```
|
```
|
||||||
|
|
||||||
Servers that can handshake in multiple protocols may have already read data
|
Successful WebSocket Upgrade responses generated by the implementation will
|
||||||
on the connection, or might have already received an entire HTTP request
|
typically look like this:
|
||||||
containing the upgrade request. Overloads of `accept` allow callers to
|
|
||||||
pass in this additional buffered handshake data.
|
[table Decorated WebSocket Upgrade HTTP Request
|
||||||
|
[[Serialized Octets][Description]]
|
||||||
|
[[
|
||||||
|
```
|
||||||
|
HTTP/1.1 101 Switching Protocols
|
||||||
|
Upgrade: websocket
|
||||||
|
Connection: upgrade
|
||||||
|
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
|
||||||
|
Server: Beast/40
|
||||||
|
```
|
||||||
|
][
|
||||||
|
The Sec-WebSocket-Accept field value is generated from the
|
||||||
|
request in a fashion specified by the WebSocket protocol.
|
||||||
|
]]]
|
||||||
|
|
||||||
|
[heading Decorators]
|
||||||
|
|
||||||
|
If the caller wishes to add or modify fields, the member functions
|
||||||
|
[link beast.ref.websocket__stream.accept_ex `accept_ex`] and
|
||||||
|
[link beast.ref.websocket__stream.async_accept_ex `async_accept_ex`]
|
||||||
|
are provided which allow an additional function object, called a
|
||||||
|
['decorator], to be passed. The decorator is invoked to modify
|
||||||
|
the HTTP Upgrade request as needed. This example sets the Server
|
||||||
|
field on the response:
|
||||||
|
```
|
||||||
|
ws.accept_ex(
|
||||||
|
[](beast::websocket::response_type& res)
|
||||||
|
{
|
||||||
|
res.fields.insert("Server", "AcmeServer");
|
||||||
|
});
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
The HTTP Upgrade response produced by the previous call will look thusly:
|
||||||
|
|
||||||
|
[table Decorated WebSocket Upgrade HTTP Request
|
||||||
|
[[Serialized Octets][Description]]
|
||||||
|
[[
|
||||||
|
```
|
||||||
|
HTTP/1.1 101 Switching Protocols
|
||||||
|
Upgrade: websocket
|
||||||
|
Connection: upgrade
|
||||||
|
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
|
||||||
|
Server: AcmeServer
|
||||||
|
```
|
||||||
|
][
|
||||||
|
When the Upgrade request fails, the implementation will still invoke
|
||||||
|
the decorator to modify the response. In this case, the response
|
||||||
|
object will have a status code other than 101.
|
||||||
|
|
||||||
|
Undefined behavior results when the upgrade request is successful
|
||||||
|
and the decorator modifies the fields specific to perform the
|
||||||
|
WebSocket Upgrade , such as the Upgrade and Connection fields.
|
||||||
|
]]]
|
||||||
|
|
||||||
|
[heading Passing HTTP Requests]
|
||||||
|
|
||||||
|
When implementing an HTTP server that also supports WebSocket, the
|
||||||
|
server usually reads the HTTP request from the client. To detect when
|
||||||
|
the incoming HTTP request is a WebSocket Upgrade request, the function
|
||||||
|
[link beast.ref.websocket__is_upgrade `is_upgrade`] may be used.
|
||||||
|
|
||||||
|
Once the caller determines that the HTTP request is a WebSocket Upgrade,
|
||||||
|
additional overloads of
|
||||||
|
[link beast.ref.websocket__stream.accept `accept`],
|
||||||
|
[link beast.ref.websocket__stream.accept_ex `accept_ex`],
|
||||||
|
[link beast.ref.websocket__stream.async_accept `async_accept`], and
|
||||||
|
[link beast.ref.websocket__stream.async_accept_ex `async_accept_ex`]
|
||||||
|
are provided which receive the entire HTTP request header as an object
|
||||||
|
to perform the handshake. In this example, the request is first read
|
||||||
|
in using the HTTP algorithms, and then passed to a newly constructed
|
||||||
|
stream:
|
||||||
|
```
|
||||||
|
void handle_connection(boost::asio::ip::tcp::socket& sock)
|
||||||
|
{
|
||||||
|
beast::flat_buffer buffer;
|
||||||
|
beast::http::request<beast::http::string_body> req;
|
||||||
|
beast::http::read(sock, buffer, req);
|
||||||
|
if(beast::websocket::is_upgrade(req))
|
||||||
|
{
|
||||||
|
beast::websocket::stream<decltype(sock)> ws{std::move(sock)};
|
||||||
|
ws.accept(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
[heading Buffered Handshakes]
|
||||||
|
|
||||||
|
Sometimes a server implementation wishes to read octets on the stream
|
||||||
|
in order to route the incoming request. For example, a server may read
|
||||||
|
the first 6 octets after accepting an incoming connection to determine
|
||||||
|
if a TLS protocol is being negotiated, and choose a suitable implementation
|
||||||
|
at run-time. In the case where the server wishes to accept the incoming
|
||||||
|
request as an HTTP WebSocket Upgrade request, additional overloads of
|
||||||
|
[link beast.ref.websocket__stream.accept `accept`],
|
||||||
|
[link beast.ref.websocket__stream.accept_ex `accept_ex`],
|
||||||
|
[link beast.ref.websocket__stream.async_accept `async_accept`], and
|
||||||
|
[link beast.ref.websocket__stream.async_accept_ex `async_accept_ex`]
|
||||||
|
are provided which receive the additional buffered octects and consume
|
||||||
|
them as part of the handshake.
|
||||||
|
|
||||||
|
In this example, the server reads the initial HTTP message into the
|
||||||
|
specified dynamic buffer as an octet sequence in the buffer's output
|
||||||
|
area, and later uses those octets to attempt an HTTP WebSocket Upgrade:
|
||||||
```
|
```
|
||||||
void do_accept(boost::asio::ip::tcp::socket& sock)
|
void do_accept(boost::asio::ip::tcp::socket& sock)
|
||||||
{
|
{
|
||||||
@@ -195,93 +396,6 @@ void do_accept(boost::asio::ip::tcp::socket& sock)
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Alternatively, the caller can pass an entire HTTP request if it was
|
|
||||||
obtained elsewhere:
|
|
||||||
```
|
|
||||||
void do_accept(boost::asio::ip::tcp::socket& sock)
|
|
||||||
{
|
|
||||||
boost::asio::streambuf sb;
|
|
||||||
beast::http::request<http::empty_body> request;
|
|
||||||
beast::http::read(sock, sb, request);
|
|
||||||
if(beast::http::is_upgrade(request))
|
|
||||||
{
|
|
||||||
websocket::stream<ip::tcp::socket&> ws{sock};
|
|
||||||
ws.accept(request);
|
|
||||||
...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
[heading Decorators]
|
|
||||||
|
|
||||||
Often, callers may need the handshake HTTP request and response objects
|
|
||||||
generated by the implementation to contain additional HTTP fields. Some
|
|
||||||
examples include:
|
|
||||||
|
|
||||||
* Setting the "User-Agent" or "Server" fields to a custom value
|
|
||||||
* Announcing a subprotocol by setting the "Sec-WebSocket-Protocol" field
|
|
||||||
* Adding fields used for HTTP's Basic Authentication
|
|
||||||
|
|
||||||
To achieve this, the websocket interface provides the functions
|
|
||||||
[link beast.ref.websocket__stream.handshake_ex `handshake_ex`],
|
|
||||||
[link beast.ref.websocket__stream.async_handshake_ex `async_handshake_ex`],
|
|
||||||
[link beast.ref.websocket__stream.accept_ex `accept_ex`], and
|
|
||||||
[link beast.ref.websocket__stream.async_accept_ex `async_accept_ex`]
|
|
||||||
which allow passing of an additional decorator parameter. This parameter is
|
|
||||||
a function object to invoke which takes a writable reference to the handshake
|
|
||||||
message. The function is called after the implementation creates the message,
|
|
||||||
providing an opportunity for further modification. For client handshakes
|
|
||||||
using
|
|
||||||
[link beast.ref.websocket__stream.handshake_ex `handshake_ex`] or
|
|
||||||
[link beast.ref.websocket__stream.async_handshake_ex `async_handshake_ex`],
|
|
||||||
the message is passed as a reference to
|
|
||||||
[link beast.ref.websocket__request_type `request_type`]. Here is an example
|
|
||||||
that sets the user agent for a client request:
|
|
||||||
|
|
||||||
```
|
|
||||||
ws.handshake_ex("ws.example.com:80", "/",
|
|
||||||
[](request_type& req)
|
|
||||||
{
|
|
||||||
req.fields.insert("User-Agent", "Beast Example");
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
For server handshakes using
|
|
||||||
[link beast.ref.websocket__stream.accept_ex `accept_ex`], and
|
|
||||||
[link beast.ref.websocket__stream.async_accept_ex `async_accept_ex`] the function
|
|
||||||
object receives the message as a reference to
|
|
||||||
[link beast.ref.websocket__response_type `response_type`].
|
|
||||||
Here is an example that sets the server field:
|
|
||||||
|
|
||||||
```
|
|
||||||
ws.accept_ex(
|
|
||||||
[](response_type& res)
|
|
||||||
{
|
|
||||||
res.fields.insert("Server", "Beast Example");
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
[heading Response Filtering]
|
|
||||||
|
|
||||||
When a client receives an HTTP Upgrade response from the server indicating
|
|
||||||
a successful upgrade, the caller may wish to perform additional validation
|
|
||||||
on the received HTTP response message. For example, to check that the
|
|
||||||
response to a basic authentication challenge is valid. To achieve this,
|
|
||||||
the functions
|
|
||||||
[link beast.ref.websocket__stream.handshake `handshake`],
|
|
||||||
[link beast.ref.websocket__stream.handshake_ex `handshake_ex`] or
|
|
||||||
[link beast.ref.websocket__stream.async_handshake `async_handshake`],
|
|
||||||
[link beast.ref.websocket__stream.async_handshake_ex `async_handshake_ex`],
|
|
||||||
have an additional set of overloads which store the received HTTP message
|
|
||||||
in the callers parameter, which must be a reference to type
|
|
||||||
[link beast.ref.websocket__response_type `response_type`], like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
response_type res;
|
|
||||||
ws.handshake(res, "ws.example.com:80", "/");
|
|
||||||
// res now contains the complete HTTP response.
|
|
||||||
```
|
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
|
|
||||||
@@ -310,11 +424,7 @@ void echo(beast::websocket::stream<boost::asio::ip::tcp::socket>& ws)
|
|||||||
to perform other operations.
|
to perform other operations.
|
||||||
]
|
]
|
||||||
|
|
||||||
[endsect]
|
[heading Frames]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[section:frames Frames]
|
|
||||||
|
|
||||||
Some use-cases make it impractical or impossible to buffer the entire
|
Some use-cases make it impractical or impossible to buffer the entire
|
||||||
message ahead of time:
|
message ahead of time:
|
||||||
@@ -470,12 +580,12 @@ the fragments:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
[section:buffers Buffers]
|
[section:notes Notes]
|
||||||
|
|
||||||
Because calls to read data may return a variable amount of bytes, the
|
Because calls to read data may return a variable amount of bytes, the
|
||||||
interface to calls that read data require an object that meets the requirements
|
interface to calls that read data require an object that meets the requirements
|
||||||
of [link beast.ref.DynamicBuffer [*`DynamicBuffer`]]. This concept is modeled on
|
of [link beast.ref.DynamicBuffer [*`DynamicBuffer`]]. This concept is modeled on
|
||||||
[@http://www.boost.org/doc/libs/1_64_0/doc/html/boost_asio/reference/basic_streambuf.html `boost::asio::basic_streambuf`].
|
[@http://www.boost.org/doc/html/boost_asio/reference/basic_streambuf.html `boost::asio::basic_streambuf`].
|
||||||
|
|
||||||
The implementation does not perform queueing or buffering of messages. If
|
The implementation does not perform queueing or buffering of messages. If
|
||||||
desired, these features should be provided by callers. The impact of this
|
desired, these features should be provided by callers. The impact of this
|
||||||
@@ -483,11 +593,7 @@ design is that library users are in full control of the allocation strategy
|
|||||||
used to store data and the back-pressure applied on the read and write side
|
used to store data and the back-pressure applied on the read and write side
|
||||||
of the underlying TCP/IP connection.
|
of the underlying TCP/IP connection.
|
||||||
|
|
||||||
[endsect]
|
[heading Asynchronous Operations]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[section:async Asynchronous interface]
|
|
||||||
|
|
||||||
Asynchronous versions are available for all functions:
|
Asynchronous versions are available for all functions:
|
||||||
```
|
```
|
||||||
@@ -513,24 +619,16 @@ void echo(websocket::stream<ip::tcp::socket>& ws,
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
[endsect]
|
[heading The io_service]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[section:io_service The io_service]
|
|
||||||
|
|
||||||
The creation and operation of the
|
The creation and operation of the
|
||||||
[@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/io_service.html `boost::asio::io_service`]
|
[@http://www.boost.org/doc/html/boost_asio/reference/io_service.html `boost::asio::io_service`]
|
||||||
associated with the underlying stream is left to the callers, permitting any
|
associated with the underlying stream is left to the callers, permitting any
|
||||||
implementation strategy including one that does not require threads for
|
implementation strategy including one that does not require threads for
|
||||||
environments where threads are unavailable. Beast.WebSocket itself does not
|
environments where threads are unavailable. Beast WebSocket itself does not
|
||||||
use or require threads.
|
use or require threads.
|
||||||
|
|
||||||
[endsect]
|
[heading Thread Safety]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[section:threads Thread Safety]
|
|
||||||
|
|
||||||
Like a regular asio socket, a [link beast.ref.websocket__stream `stream`] is
|
Like a regular asio socket, a [link beast.ref.websocket__stream `stream`] is
|
||||||
not thread safe. Callers are responsible for synchronizing operations on the
|
not thread safe. Callers are responsible for synchronizing operations on the
|
||||||
|
@@ -5,6 +5,17 @@ GroupSources(include/beast beast)
|
|||||||
|
|
||||||
GroupSources(examples "/")
|
GroupSources(examples "/")
|
||||||
|
|
||||||
|
add_executable (echo-op
|
||||||
|
${BEAST_INCLUDES}
|
||||||
|
echo_op.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
if (NOT WIN32)
|
||||||
|
target_link_libraries(echo-op ${Boost_LIBRARIES} Threads::Threads)
|
||||||
|
else()
|
||||||
|
target_link_libraries(echo-op ${Boost_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
add_executable (http-crawl
|
add_executable (http-crawl
|
||||||
${BEAST_INCLUDES}
|
${BEAST_INCLUDES}
|
||||||
${EXTRAS_INCLUDES}
|
${EXTRAS_INCLUDES}
|
||||||
|
@@ -5,6 +5,10 @@
|
|||||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
#
|
#
|
||||||
|
|
||||||
|
exe echo-op :
|
||||||
|
echo_op.cpp
|
||||||
|
;
|
||||||
|
|
||||||
exe http-crawl :
|
exe http-crawl :
|
||||||
http_crawl.cpp
|
http_crawl.cpp
|
||||||
urls_large_data.cpp
|
urls_large_data.cpp
|
230
examples/echo_op.cpp
Normal file
230
examples/echo_op.cpp
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2013-2017 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)
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <beast/core.hpp>
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
// This composed operation reads a line of input and echoes it back.
|
||||||
|
//
|
||||||
|
template<class AsyncStream, class Handler>
|
||||||
|
class echo_op
|
||||||
|
{
|
||||||
|
// This holds all of the state information required by the operation.
|
||||||
|
struct state
|
||||||
|
{
|
||||||
|
// The stream to read and write to
|
||||||
|
AsyncStream& stream;
|
||||||
|
|
||||||
|
// Indicates what step in the operation's state machine
|
||||||
|
// to perform next, starting from zero.
|
||||||
|
int step = 0;
|
||||||
|
|
||||||
|
// The buffer used to hold the input and output data.
|
||||||
|
// Note that we use a custom allocator for performance,
|
||||||
|
// this allows the implementation of the io_service to
|
||||||
|
// make efficient re-use of memory allocated by composed
|
||||||
|
// operations during continuations.
|
||||||
|
//
|
||||||
|
boost::asio::basic_streambuf<beast::handler_alloc<char, Handler>> buffer;
|
||||||
|
|
||||||
|
// handler_ptr requires that the first parameter to the
|
||||||
|
// contained object constructor is a reference to the
|
||||||
|
// managed final completion handler.
|
||||||
|
//
|
||||||
|
explicit state(Handler& handler, AsyncStream& stream_)
|
||||||
|
: stream(stream_)
|
||||||
|
, buffer((std::numeric_limits<std::size_t>::max)(),
|
||||||
|
beast::handler_alloc<char, Handler>{handler})
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// This smart pointer container allocates our state using the
|
||||||
|
// memory allocation hooks associated with the final completion
|
||||||
|
// handler, manages the lifetime of that handler for us, and
|
||||||
|
// enforces the destroy-before-invocation requirement on memory
|
||||||
|
// allocated using the hooks.
|
||||||
|
//
|
||||||
|
beast::handler_ptr<state, Handler> p_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Boost.Asio requires that handlers are CopyConstructible.
|
||||||
|
// In some cases, it takes advantage of handlers that are
|
||||||
|
// MoveConstructible. This operation supports both.
|
||||||
|
//
|
||||||
|
echo_op(echo_op&&) = default;
|
||||||
|
echo_op(echo_op const&) = default;
|
||||||
|
|
||||||
|
// The constructor simply creates our state variables in
|
||||||
|
// the smart pointer container.
|
||||||
|
//
|
||||||
|
template<class DeducedHandler, class... Args>
|
||||||
|
echo_op(AsyncStream& stream, DeducedHandler&& handler)
|
||||||
|
: p_(std::forward<DeducedHandler>(handler), stream)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determines if the next asynchronous operation represents a
|
||||||
|
// continuation of the asynchronous flow of control associated
|
||||||
|
// with the final handler. If we are past step one, it means
|
||||||
|
// we have performed an asynchronous operation therefore any
|
||||||
|
// subsequent operation would represent a continuation.
|
||||||
|
// Otherwise, we propagate the handler's associated value of
|
||||||
|
// is_continuation. Getting this right means the implementation
|
||||||
|
// may schedule the invokation of the invoked functions more
|
||||||
|
// efficiently.
|
||||||
|
//
|
||||||
|
friend bool asio_handler_is_continuation(echo_op* op)
|
||||||
|
{
|
||||||
|
// This next call is structured to permit argument
|
||||||
|
// dependent lookup to take effect.
|
||||||
|
using boost::asio::asio_handler_is_continuation;
|
||||||
|
|
||||||
|
// Always use std::addressof to pass the pointer to the handler,
|
||||||
|
// otherwise an unwanted overload of operator& may be called instead.
|
||||||
|
return op->p_->step > 1 ||
|
||||||
|
asio_handler_is_continuation(std::addressof(op->p_.handler()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handler hook forwarding. These free functions invoke the hooks
|
||||||
|
// associated with the final completion handler. In effect, they
|
||||||
|
// make the Asio implementation treat our composed operation the
|
||||||
|
// same way it would treat the final completion handler for the
|
||||||
|
// purpose of memory allocation and invocation.
|
||||||
|
//
|
||||||
|
// Our implementation just passes through the call to the hook
|
||||||
|
// associated with the final handler.
|
||||||
|
|
||||||
|
friend void* asio_handler_allocate(std::size_t size, echo_op* op)
|
||||||
|
{
|
||||||
|
using boost::asio::asio_handler_allocate;
|
||||||
|
return asio_handler_allocate(size, std::addressof(op->p_.handler()));
|
||||||
|
}
|
||||||
|
|
||||||
|
friend void asio_handler_deallocate(void* p, std::size_t size, echo_op* op)
|
||||||
|
{
|
||||||
|
using boost::asio::asio_handler_deallocate;
|
||||||
|
return asio_handler_deallocate(p, size, std::addressof(op->p_.handler()));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Function>
|
||||||
|
friend void asio_handler_invoke(Function&& f, echo_op* op)
|
||||||
|
{
|
||||||
|
using boost::asio::asio_handler_invoke;
|
||||||
|
return asio_handler_invoke(f, std::addressof(op->p_.handler()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Our main entry point. This will get called as our
|
||||||
|
// intermediate operations complete. Definition below.
|
||||||
|
//
|
||||||
|
void operator()(beast::error_code ec, std::size_t bytes_transferred);
|
||||||
|
};
|
||||||
|
|
||||||
|
// We are callable with the signature void(error_code, bytes_transferred),
|
||||||
|
// allowing `*this` to be used as both a ReadHandler and a WriteHandler.
|
||||||
|
//
|
||||||
|
template<class AsyncStream, class Handler>
|
||||||
|
void echo_op<AsyncStream, Handler>::
|
||||||
|
operator()(beast::error_code ec, std::size_t bytes_transferred)
|
||||||
|
{
|
||||||
|
// Store a reference to our state. The address of the state won't
|
||||||
|
// change, and this solves the problem where dereferencing the
|
||||||
|
// data member is undefined after a move.
|
||||||
|
auto& p = *p_;
|
||||||
|
|
||||||
|
// Now perform the next step in the state machine
|
||||||
|
switch(ec ? 2 : p.step)
|
||||||
|
{
|
||||||
|
// initial entry
|
||||||
|
case 0:
|
||||||
|
// read up to the first newline
|
||||||
|
p.step = 1;
|
||||||
|
return boost::asio::async_read_until(p.stream, p.buffer, "\n", std::move(*this));
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
// write everything back
|
||||||
|
p.step = 2;
|
||||||
|
return boost::asio::async_write(p.stream, p.buffer.data(), std::move(*this));
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invoke the final handler. If we wanted to pass any arguments
|
||||||
|
// which come from our state, they would have to be moved to the
|
||||||
|
// stack first, since the `handler_ptr` guarantees that the state
|
||||||
|
// is destroyed before
|
||||||
|
// the handler is invoked.
|
||||||
|
//
|
||||||
|
p_.invoke(ec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read a line and echo it back
|
||||||
|
//
|
||||||
|
template<class AsyncStream, class CompletionToken>
|
||||||
|
beast::async_return_type<CompletionToken, void(beast::error_code)>
|
||||||
|
async_echo(AsyncStream& stream, CompletionToken&& token)
|
||||||
|
{
|
||||||
|
// Make sure stream meets the requirements. We use static_assert
|
||||||
|
// instead of letting the compiler generate several pages of hard
|
||||||
|
// to read error messages.
|
||||||
|
//
|
||||||
|
static_assert(beast::is_async_stream<AsyncStream>::value,
|
||||||
|
"AsyncStream requirements not met");
|
||||||
|
|
||||||
|
// This helper manages some of the handler's lifetime and
|
||||||
|
// uses the result and handler specializations associated with
|
||||||
|
// the completion token to help customize the return value.
|
||||||
|
//
|
||||||
|
beast::async_completion<CompletionToken, void(beast::error_code)> init{token};
|
||||||
|
|
||||||
|
// Create the composed operation and launch it. This is a constructor
|
||||||
|
// call followed by invocation of operator(). We use BEAST_HANDLER_TYPE
|
||||||
|
// to convert the completion token into the correct handler type,
|
||||||
|
// allowing user defined specializations of the async result template
|
||||||
|
// to take effect.
|
||||||
|
//
|
||||||
|
echo_op<AsyncStream, beast::handler_type<CompletionToken, void(beast::error_code)>>{
|
||||||
|
stream, init.completion_handler}(beast::error_code{}, 0);
|
||||||
|
|
||||||
|
// This hook lets the caller see a return value when appropriate.
|
||||||
|
// For example this might return std::future<error_code> if
|
||||||
|
// CompletionToken is boost::asio::use_future, or this might
|
||||||
|
// return an error code if CompletionToken specifies a coroutine.
|
||||||
|
//
|
||||||
|
return init.result.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
using address_type = boost::asio::ip::address;
|
||||||
|
using socket_type = boost::asio::ip::tcp::socket;
|
||||||
|
using endpoint_type = boost::asio::ip::tcp::endpoint;
|
||||||
|
|
||||||
|
// Create a listening socket, accept a connection, perform
|
||||||
|
// the echo, and then shut everything down and exit.
|
||||||
|
boost::asio::io_service ios;
|
||||||
|
socket_type sock{ios};
|
||||||
|
{
|
||||||
|
boost::asio::ip::tcp::acceptor acceptor{ios};
|
||||||
|
endpoint_type ep{address_type::from_string("0.0.0.0"), 0};
|
||||||
|
acceptor.open(ep.protocol());
|
||||||
|
acceptor.bind(ep);
|
||||||
|
acceptor.listen();
|
||||||
|
acceptor.accept(sock);
|
||||||
|
}
|
||||||
|
async_echo(sock,
|
||||||
|
[&](beast::error_code ec)
|
||||||
|
{
|
||||||
|
});
|
||||||
|
ios.run();
|
||||||
|
return 0;
|
||||||
|
}
|
@@ -13,14 +13,12 @@
|
|||||||
#include <beast/core/async_result.hpp>
|
#include <beast/core/async_result.hpp>
|
||||||
#include <beast/core/bind_handler.hpp>
|
#include <beast/core/bind_handler.hpp>
|
||||||
#include <beast/core/buffer_cat.hpp>
|
#include <beast/core/buffer_cat.hpp>
|
||||||
#include <beast/core/buffer_concepts.hpp>
|
|
||||||
#include <beast/core/buffers_adapter.hpp>
|
#include <beast/core/buffers_adapter.hpp>
|
||||||
#include <beast/core/consuming_buffers.hpp>
|
#include <beast/core/consuming_buffers.hpp>
|
||||||
#include <beast/core/buffered_read_stream.hpp>
|
#include <beast/core/buffered_read_stream.hpp>
|
||||||
#include <beast/core/error.hpp>
|
#include <beast/core/error.hpp>
|
||||||
#include <beast/core/flat_buffer.hpp>
|
#include <beast/core/flat_buffer.hpp>
|
||||||
#include <beast/core/handler_alloc.hpp>
|
#include <beast/core/handler_alloc.hpp>
|
||||||
#include <beast/core/handler_concepts.hpp>
|
|
||||||
#include <beast/core/handler_helpers.hpp>
|
#include <beast/core/handler_helpers.hpp>
|
||||||
#include <beast/core/handler_ptr.hpp>
|
#include <beast/core/handler_ptr.hpp>
|
||||||
#include <beast/core/multi_buffer.hpp>
|
#include <beast/core/multi_buffer.hpp>
|
||||||
@@ -28,6 +26,6 @@
|
|||||||
#include <beast/core/prepare_buffer.hpp>
|
#include <beast/core/prepare_buffer.hpp>
|
||||||
#include <beast/core/static_buffer.hpp>
|
#include <beast/core/static_buffer.hpp>
|
||||||
#include <beast/core/static_string.hpp>
|
#include <beast/core/static_string.hpp>
|
||||||
#include <beast/core/stream_concepts.hpp>
|
#include <beast/core/type_traits.hpp>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -9,8 +9,7 @@
|
|||||||
#define BEAST_ASYNC_COMPLETION_HPP
|
#define BEAST_ASYNC_COMPLETION_HPP
|
||||||
|
|
||||||
#include <beast/config.hpp>
|
#include <beast/config.hpp>
|
||||||
#include <beast/core/handler_concepts.hpp>
|
#include <beast/core/type_traits.hpp>
|
||||||
#include <beast/core/detail/type_traits.hpp>
|
|
||||||
#include <boost/asio/async_result.hpp>
|
#include <boost/asio/async_result.hpp>
|
||||||
#include <boost/asio/handler_type.hpp>
|
#include <boost/asio/handler_type.hpp>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
@@ -18,11 +17,11 @@
|
|||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
/** An interface for customising the behaviour of an initiating function.
|
/** An interface for customising the behaviour of an asynchronous initiation function.
|
||||||
|
|
||||||
The async_result class is used for determining:
|
This class is used for determining:
|
||||||
|
|
||||||
@li the concrete completion handler type to be called at the end of the
|
@li The concrete completion handler type to be called at the end of the
|
||||||
asynchronous operation;
|
asynchronous operation;
|
||||||
|
|
||||||
@li the initiating function return type; and
|
@li the initiating function return type; and
|
||||||
@@ -91,12 +90,6 @@ public:
|
|||||||
allows customization of the return type of the initiating function, and the
|
allows customization of the return type of the initiating function, and the
|
||||||
function signature of the final handler.
|
function signature of the final handler.
|
||||||
|
|
||||||
@tparam CompletionToken A completion handler, or a user defined type
|
|
||||||
with specializations for customizing the return type (for example,
|
|
||||||
`boost::asio::use_future` or `boost::asio::yield_context`).
|
|
||||||
|
|
||||||
@tparam Signature The callable signature of the final completion handler.
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
@code
|
@code
|
||||||
...
|
...
|
||||||
@@ -150,7 +143,7 @@ struct async_completion
|
|||||||
, result(completion_handler)
|
, result(completion_handler)
|
||||||
{
|
{
|
||||||
// CompletionToken is not invokable with the given signature
|
// CompletionToken is not invokable with the given signature
|
||||||
static_assert(is_CompletionHandler<
|
static_assert(is_completion_handler<
|
||||||
completion_handler_type, Signature>::value,
|
completion_handler_type, Signature>::value,
|
||||||
"CompletionToken requirements not met: signature mismatch");
|
"CompletionToken requirements not met: signature mismatch");
|
||||||
}
|
}
|
||||||
@@ -167,37 +160,11 @@ struct async_completion
|
|||||||
CompletionToken>::type, Signature> result;
|
CompletionToken>::type, Signature> result;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Convert a completion token to the correct completion handler type.
|
|
||||||
|
|
||||||
This helps asynchronous initiation functions to meet the
|
|
||||||
requirements of the Extensible Asynchronous Model.
|
|
||||||
|
|
||||||
@tparam CompletionToken Specifies the model used to obtain the result of
|
|
||||||
the asynchronous operation.
|
|
||||||
|
|
||||||
@tparam Signature The call signature for the completion handler type invoked
|
|
||||||
on completion of the asynchronous operation.
|
|
||||||
|
|
||||||
@see @ref async_completion, @ref async_return_type
|
|
||||||
*/
|
|
||||||
template<class CompletionToken, typename Signature>
|
template<class CompletionToken, typename Signature>
|
||||||
using handler_type = typename beast::async_result<
|
using handler_type = typename beast::async_result<
|
||||||
typename std::decay<CompletionToken>::type,
|
typename std::decay<CompletionToken>::type,
|
||||||
Signature>::completion_handler_type;
|
Signature>::completion_handler_type;
|
||||||
|
|
||||||
/** Determine the return value of an asynchronous initiation function
|
|
||||||
|
|
||||||
This helps asynchronous initiation functions to meet the
|
|
||||||
requirements of the Extensible Asynchronous Model.
|
|
||||||
|
|
||||||
@tparam CompletionToken Specifies the model used to obtain the result of
|
|
||||||
the asynchronous operation.
|
|
||||||
|
|
||||||
@tparam Signature The call signature for the completion handler type invoked
|
|
||||||
on completion of the asynchronous operation.
|
|
||||||
|
|
||||||
@see @ref async_completion, @ref handler_type
|
|
||||||
*/
|
|
||||||
template<class CompletionToken, typename Signature>
|
template<class CompletionToken, typename Signature>
|
||||||
using async_return_type = typename beast::async_result<
|
using async_return_type = typename beast::async_result<
|
||||||
typename std::decay<CompletionToken>::type,
|
typename std::decay<CompletionToken>::type,
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
#define BEAST_BIND_HANDLER_HPP
|
#define BEAST_BIND_HANDLER_HPP
|
||||||
|
|
||||||
#include <beast/config.hpp>
|
#include <beast/config.hpp>
|
||||||
#include <beast/core/handler_concepts.hpp>
|
#include <beast/core/type_traits.hpp>
|
||||||
#include <beast/core/detail/bind_handler.hpp>
|
#include <beast/core/detail/bind_handler.hpp>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@@ -24,24 +24,23 @@ namespace beast {
|
|||||||
the returned handler, which provides the same `io_service`
|
the returned handler, which provides the same `io_service`
|
||||||
execution guarantees as the original handler.
|
execution guarantees as the original handler.
|
||||||
|
|
||||||
Unlike `io_service::wrap`, the returned handler can be used in
|
Unlike `boost::asio::io_service::wrap`, the returned handler can
|
||||||
a subsequent call to `io_service::post` instead of
|
be used in a subsequent call to `boost::asio::io_service::post`
|
||||||
`io_service::dispatch`, to ensure that the handler will not be
|
instead of `boost::asio::io_service::dispatch`, to ensure that
|
||||||
invoked immediately by the calling function.
|
the handler will not be invoked immediately by the calling
|
||||||
|
function.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@code
|
@code
|
||||||
|
|
||||||
template<class AsyncReadStream, class ReadHandler>
|
template<class AsyncReadStream, class ReadHandler>
|
||||||
void
|
void
|
||||||
do_cancel(AsyncReadStream& stream, ReadHandler&& handler)
|
signal_aborted(AsyncReadStream& stream, ReadHandler&& handler)
|
||||||
{
|
{
|
||||||
stream.get_io_service().post(
|
stream.get_io_service().post(
|
||||||
bind_handler(std::forward<ReadHandler>(handler),
|
bind_handler(std::forward<ReadHandler>(handler),
|
||||||
boost::asio::error::operation_aborted, 0));
|
boost::asio::error::operation_aborted, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
@param handler The handler to wrap.
|
@param handler The handler to wrap.
|
||||||
@@ -58,7 +57,7 @@ detail::bound_handler<
|
|||||||
#endif
|
#endif
|
||||||
bind_handler(Handler&& handler, Args&&... args)
|
bind_handler(Handler&& handler, Args&&... args)
|
||||||
{
|
{
|
||||||
static_assert(is_CompletionHandler<
|
static_assert(is_completion_handler<
|
||||||
Handler, void(Args...)>::value,
|
Handler, void(Args...)>::value,
|
||||||
"Handler requirements not met");
|
"Handler requirements not met");
|
||||||
return detail::bound_handler<typename std::decay<
|
return detail::bound_handler<typename std::decay<
|
||||||
|
@@ -34,8 +34,8 @@ namespace beast {
|
|||||||
@return A new buffer sequence that represents the concatenation of
|
@return A new buffer sequence that represents the concatenation of
|
||||||
the input buffer sequences. This buffer sequence will be a
|
the input buffer sequences. This buffer sequence will be a
|
||||||
@b MutableBufferSequence if each of the passed buffer sequences is
|
@b MutableBufferSequence if each of the passed buffer sequences is
|
||||||
also a @b MutableBufferSequence, else the returned buffer sequence
|
also a @b MutableBufferSequence; otherwise the returned buffer
|
||||||
will be a @b ConstBufferSequence.
|
sequence will be a @b ConstBufferSequence.
|
||||||
*/
|
*/
|
||||||
#if BEAST_DOXYGEN
|
#if BEAST_DOXYGEN
|
||||||
template<class... BufferSequence>
|
template<class... BufferSequence>
|
||||||
|
@@ -1,55 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2013-2017 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_BUFFER_CONCEPTS_HPP
|
|
||||||
#define BEAST_BUFFER_CONCEPTS_HPP
|
|
||||||
|
|
||||||
#include <beast/config.hpp>
|
|
||||||
#include <beast/core/detail/buffer_concepts.hpp>
|
|
||||||
#include <boost/asio/buffer.hpp>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
/// Determine if `T` meets the requirements of @b ConstBufferSequence.
|
|
||||||
template<class T>
|
|
||||||
#if BEAST_DOXYGEN
|
|
||||||
struct is_const_buffer_sequence : std::integral_constant<bool, ...>
|
|
||||||
#else
|
|
||||||
struct is_const_buffer_sequence :
|
|
||||||
detail::is_buffer_sequence<T,
|
|
||||||
boost::asio::const_buffer>::type
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Determine if `T` meets the requirements of @b DynamicBuffer.
|
|
||||||
template<class T>
|
|
||||||
#if BEAST_DOXYGEN
|
|
||||||
struct is_dynamic_buffer : std::integral_constant<bool, ...>
|
|
||||||
#else
|
|
||||||
struct is_dynamic_buffer :
|
|
||||||
detail::is_dynamic_buffer<T>::type
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Determine if `T` meets the requirements of @b MutableBufferSequence.
|
|
||||||
template<class T>
|
|
||||||
#if BEAST_DOXYGEN
|
|
||||||
struct is_mutable_buffer_sequence : std::integral_constant<bool, ...>
|
|
||||||
#else
|
|
||||||
struct is_mutable_buffer_sequence :
|
|
||||||
detail::is_buffer_sequence<T,
|
|
||||||
boost::asio::mutable_buffer>::type
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
|
|
||||||
#endif
|
|
@@ -10,11 +10,9 @@
|
|||||||
|
|
||||||
#include <beast/config.hpp>
|
#include <beast/config.hpp>
|
||||||
#include <beast/core/async_result.hpp>
|
#include <beast/core/async_result.hpp>
|
||||||
#include <beast/core/buffer_concepts.hpp>
|
|
||||||
#include <beast/core/error.hpp>
|
#include <beast/core/error.hpp>
|
||||||
#include <beast/core/stream_concepts.hpp>
|
|
||||||
#include <beast/core/multi_buffer.hpp>
|
#include <beast/core/multi_buffer.hpp>
|
||||||
#include <beast/core/detail/type_traits.hpp>
|
#include <beast/core/type_traits.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <boost/asio/io_service.hpp>
|
#include <boost/asio/io_service.hpp>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@@ -26,7 +24,7 @@ namespace beast {
|
|||||||
|
|
||||||
This wraps a @b Stream implementation so that calls to write are
|
This wraps a @b Stream implementation so that calls to write are
|
||||||
passed through to the underlying stream, while calls to read will
|
passed through to the underlying stream, while calls to read will
|
||||||
first consume the input sequence stored in a @b `DynamicBuffer` which
|
first consume the input sequence stored in a @b DynamicBuffer which
|
||||||
is part of the object.
|
is part of the object.
|
||||||
|
|
||||||
The use-case for this class is different than that of the
|
The use-case for this class is different than that of the
|
||||||
@@ -292,7 +290,7 @@ public:
|
|||||||
std::size_t
|
std::size_t
|
||||||
write_some(ConstBufferSequence const& buffers)
|
write_some(ConstBufferSequence const& buffers)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncWriteStream<next_layer_type>::value,
|
static_assert(is_sync_write_stream<next_layer_type>::value,
|
||||||
"SyncWriteStream requirements not met");
|
"SyncWriteStream requirements not met");
|
||||||
return next_layer_.write_some(buffers);
|
return next_layer_.write_some(buffers);
|
||||||
}
|
}
|
||||||
@@ -314,7 +312,7 @@ public:
|
|||||||
write_some(ConstBufferSequence const& buffers,
|
write_some(ConstBufferSequence const& buffers,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncWriteStream<next_layer_type>::value,
|
static_assert(is_sync_write_stream<next_layer_type>::value,
|
||||||
"SyncWriteStream requirements not met");
|
"SyncWriteStream requirements not met");
|
||||||
return next_layer_.write_some(buffers, ec);
|
return next_layer_.write_some(buffers, ec);
|
||||||
}
|
}
|
||||||
|
@@ -9,16 +9,16 @@
|
|||||||
#define BEAST_BUFFERS_ADAPTER_HPP
|
#define BEAST_BUFFERS_ADAPTER_HPP
|
||||||
|
|
||||||
#include <beast/config.hpp>
|
#include <beast/config.hpp>
|
||||||
#include <beast/core/buffer_concepts.hpp>
|
#include <beast/core/type_traits.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
/** Adapts a @b `MutableBufferSequence` into a @b `DynamicBuffer`.
|
/** Adapts a @b MutableBufferSequence into a @b DynamicBuffer.
|
||||||
|
|
||||||
This class wraps a @b `MutableBufferSequence` to meet the requirements
|
This class wraps a @b MutableBufferSequence to meet the requirements
|
||||||
of @b `DynamicBuffer`. Upon construction the input and output sequences are
|
of @b DynamicBuffer. Upon construction the input and output sequences are
|
||||||
empty. A copy of the mutable buffer sequence object is stored; however,
|
empty. A copy of the mutable buffer sequence object is stored; however,
|
||||||
ownership of the underlying memory is not transferred. The caller is
|
ownership of the underlying memory is not transferred. The caller is
|
||||||
responsible for making sure that referenced memory remains valid
|
responsible for making sure that referenced memory remains valid
|
||||||
|
@@ -8,8 +8,7 @@
|
|||||||
#ifndef BEAST_DETAIL_BUFFER_CAT_HPP
|
#ifndef BEAST_DETAIL_BUFFER_CAT_HPP
|
||||||
#define BEAST_DETAIL_BUFFER_CAT_HPP
|
#define BEAST_DETAIL_BUFFER_CAT_HPP
|
||||||
|
|
||||||
#include <beast/core/buffer_concepts.hpp>
|
#include <beast/core/type_traits.hpp>
|
||||||
#include <beast/core/detail/type_traits.hpp>
|
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
@@ -1,180 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2013-2017 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_DETAIL_BUFFER_CONCEPTS_HPP
|
|
||||||
#define BEAST_DETAIL_BUFFER_CONCEPTS_HPP
|
|
||||||
|
|
||||||
#include <boost/asio/buffer.hpp>
|
|
||||||
#include <iterator>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
// Types that meet the requirements,
|
|
||||||
// for use with std::declval only.
|
|
||||||
template<class BufferType>
|
|
||||||
struct BufferSequence
|
|
||||||
{
|
|
||||||
using value_type = BufferType;
|
|
||||||
using const_iterator = BufferType const*;
|
|
||||||
~BufferSequence();
|
|
||||||
BufferSequence(BufferSequence const&) = default;
|
|
||||||
const_iterator begin() const noexcept;
|
|
||||||
const_iterator end() const noexcept;
|
|
||||||
};
|
|
||||||
using ConstBufferSequence =
|
|
||||||
BufferSequence<boost::asio::const_buffer>;
|
|
||||||
using MutableBufferSequence =
|
|
||||||
BufferSequence<boost::asio::mutable_buffer>;
|
|
||||||
|
|
||||||
template<class T, class BufferType>
|
|
||||||
class is_buffer_sequence
|
|
||||||
{
|
|
||||||
template<class U, class R = std::is_convertible<
|
|
||||||
typename U::value_type, BufferType> >
|
|
||||||
static R check1(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check1(...);
|
|
||||||
using type1 = decltype(check1<T>(0));
|
|
||||||
|
|
||||||
template<class U, class R = std::is_base_of<
|
|
||||||
#if 0
|
|
||||||
std::bidirectional_iterator_tag,
|
|
||||||
typename std::iterator_traits<
|
|
||||||
typename U::const_iterator>::iterator_category>>
|
|
||||||
#else
|
|
||||||
// workaround:
|
|
||||||
// boost::asio::detail::consuming_buffers::const_iterator
|
|
||||||
// is not bidirectional
|
|
||||||
std::forward_iterator_tag,
|
|
||||||
typename std::iterator_traits<
|
|
||||||
typename U::const_iterator>::iterator_category>>
|
|
||||||
#endif
|
|
||||||
static R check2(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check2(...);
|
|
||||||
using type2 = decltype(check2<T>(0));
|
|
||||||
|
|
||||||
template<class U, class R = typename
|
|
||||||
std::is_convertible<decltype(
|
|
||||||
std::declval<U>().begin()),
|
|
||||||
typename U::const_iterator>::type>
|
|
||||||
static R check3(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check3(...);
|
|
||||||
using type3 = decltype(check3<T>(0));
|
|
||||||
|
|
||||||
template<class U, class R = typename std::is_convertible<decltype(
|
|
||||||
std::declval<U>().end()),
|
|
||||||
typename U::const_iterator>::type>
|
|
||||||
static R check4(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check4(...);
|
|
||||||
using type4 = decltype(check4<T>(0));
|
|
||||||
|
|
||||||
public:
|
|
||||||
using type = std::integral_constant<bool,
|
|
||||||
std::is_copy_constructible<T>::value &&
|
|
||||||
std::is_destructible<T>::value &&
|
|
||||||
type1::value && type2::value &&
|
|
||||||
type3::value && type4::value>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class B1, class... Bn>
|
|
||||||
struct is_all_ConstBufferSequence
|
|
||||||
: std::integral_constant<bool,
|
|
||||||
is_buffer_sequence<B1, boost::asio::const_buffer>::type::value &&
|
|
||||||
is_all_ConstBufferSequence<Bn...>::value>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class B1>
|
|
||||||
struct is_all_ConstBufferSequence<B1>
|
|
||||||
: is_buffer_sequence<B1, boost::asio::const_buffer>::type
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
class is_dynamic_buffer
|
|
||||||
{
|
|
||||||
// size()
|
|
||||||
template<class U, class R = std::is_convertible<decltype(
|
|
||||||
std::declval<U const>().size()), std::size_t>>
|
|
||||||
static R check1(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check1(...);
|
|
||||||
using type1 = decltype(check1<T>(0));
|
|
||||||
|
|
||||||
// max_size()
|
|
||||||
template<class U, class R = std::is_convertible<decltype(
|
|
||||||
std::declval<U const>().max_size()), std::size_t>>
|
|
||||||
static R check2(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check2(...);
|
|
||||||
using type2 = decltype(check2<T>(0));
|
|
||||||
|
|
||||||
// capacity()
|
|
||||||
template<class U, class R = std::is_convertible<decltype(
|
|
||||||
std::declval<U const>().capacity()), std::size_t>>
|
|
||||||
static R check3(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check3(...);
|
|
||||||
using type3 = decltype(check3<T>(0));
|
|
||||||
|
|
||||||
// data()
|
|
||||||
template<class U, class R = std::integral_constant<
|
|
||||||
bool, is_buffer_sequence<decltype(
|
|
||||||
std::declval<U const>().data()),
|
|
||||||
boost::asio::const_buffer>::type::value>>
|
|
||||||
static R check4(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check4(...);
|
|
||||||
using type4 = decltype(check4<T>(0));
|
|
||||||
|
|
||||||
// prepare()
|
|
||||||
template<class U, class R = std::integral_constant<
|
|
||||||
bool, is_buffer_sequence<decltype(
|
|
||||||
std::declval<U>().prepare(1)),
|
|
||||||
boost::asio::mutable_buffer>::type::value>>
|
|
||||||
static R check5(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check5(...);
|
|
||||||
using type5 = decltype(check5<T>(0));
|
|
||||||
|
|
||||||
// commit()
|
|
||||||
template<class U, class R = decltype(
|
|
||||||
std::declval<U>().commit(1), std::true_type{})>
|
|
||||||
static R check6(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check6(...);
|
|
||||||
using type6 = decltype(check6<T>(0));
|
|
||||||
|
|
||||||
// consume
|
|
||||||
template<class U, class R = decltype(
|
|
||||||
std::declval<U>().consume(1), std::true_type{})>
|
|
||||||
static R check7(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check7(...);
|
|
||||||
using type7 = decltype(check7<T>(0));
|
|
||||||
|
|
||||||
public:
|
|
||||||
using type = std::integral_constant<bool,
|
|
||||||
type1::value
|
|
||||||
&& type2::value
|
|
||||||
//&& type3::value // Networking TS
|
|
||||||
&& type4::value
|
|
||||||
&& type5::value
|
|
||||||
&& type6::value
|
|
||||||
&& type7::value
|
|
||||||
>;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // detail
|
|
||||||
} // beast
|
|
||||||
|
|
||||||
#endif
|
|
@@ -1,134 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2013-2017 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_DETAIL_STREAM_CONCEPTS_HPP
|
|
||||||
#define BEAST_DETAIL_STREAM_CONCEPTS_HPP
|
|
||||||
|
|
||||||
#include <beast/core/buffer_concepts.hpp>
|
|
||||||
#include <beast/core/error.hpp>
|
|
||||||
#include <boost/asio/io_service.hpp>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
// Types that meet the requirements,
|
|
||||||
// for use with std::declval only.
|
|
||||||
struct StreamHandler
|
|
||||||
{
|
|
||||||
StreamHandler(StreamHandler const&) = default;
|
|
||||||
void operator()(error_code ec, std::size_t);
|
|
||||||
};
|
|
||||||
using ReadHandler = StreamHandler;
|
|
||||||
using WriteHandler = StreamHandler;
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
class has_get_io_service
|
|
||||||
{
|
|
||||||
template<class U, class R = typename std::is_same<
|
|
||||||
decltype(std::declval<U>().get_io_service()),
|
|
||||||
boost::asio::io_service&>>
|
|
||||||
static R check(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check(...);
|
|
||||||
public:
|
|
||||||
using type = decltype(check<T>(0));
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
class is_AsyncReadStream
|
|
||||||
{
|
|
||||||
template<class U, class R = decltype(
|
|
||||||
std::declval<U>().async_read_some(
|
|
||||||
std::declval<MutableBufferSequence>(),
|
|
||||||
std::declval<ReadHandler>()),
|
|
||||||
std::true_type{})>
|
|
||||||
static R check(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check(...);
|
|
||||||
using type1 = decltype(check<T>(0));
|
|
||||||
public:
|
|
||||||
using type = std::integral_constant<bool,
|
|
||||||
type1::value &&
|
|
||||||
has_get_io_service<T>::type::value>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
class is_AsyncWriteStream
|
|
||||||
{
|
|
||||||
template<class U, class R = decltype(
|
|
||||||
std::declval<U>().async_write_some(
|
|
||||||
std::declval<ConstBufferSequence>(),
|
|
||||||
std::declval<WriteHandler>()),
|
|
||||||
std::true_type{})>
|
|
||||||
static R check(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check(...);
|
|
||||||
using type1 = decltype(check<T>(0));
|
|
||||||
public:
|
|
||||||
using type = std::integral_constant<bool,
|
|
||||||
type1::value &&
|
|
||||||
has_get_io_service<T>::type::value>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
class is_SyncReadStream
|
|
||||||
{
|
|
||||||
template<class U, class R = std::is_same<decltype(
|
|
||||||
std::declval<U>().read_some(
|
|
||||||
std::declval<MutableBufferSequence>())),
|
|
||||||
std::size_t>>
|
|
||||||
static R check1(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check1(...);
|
|
||||||
using type1 = decltype(check1<T>(0));
|
|
||||||
|
|
||||||
template<class U, class R = std::is_same<decltype(
|
|
||||||
std::declval<U>().read_some(
|
|
||||||
std::declval<MutableBufferSequence>(),
|
|
||||||
std::declval<error_code&>())), std::size_t>>
|
|
||||||
static R check2(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check2(...);
|
|
||||||
using type2 = decltype(check2<T>(0));
|
|
||||||
|
|
||||||
public:
|
|
||||||
using type = std::integral_constant<bool,
|
|
||||||
type1::value && type2::value>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
class is_SyncWriteStream
|
|
||||||
{
|
|
||||||
template<class U, class R = std::is_same<decltype(
|
|
||||||
std::declval<U>().write_some(
|
|
||||||
std::declval<ConstBufferSequence>())),
|
|
||||||
std::size_t>>
|
|
||||||
static R check1(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check1(...);
|
|
||||||
using type1 = decltype(check1<T>(0));
|
|
||||||
|
|
||||||
template<class U, class R = std::is_same<decltype(
|
|
||||||
std::declval<U>().write_some(
|
|
||||||
std::declval<ConstBufferSequence>(),
|
|
||||||
std::declval<error_code&>())), std::size_t>>
|
|
||||||
static R check2(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check2(...);
|
|
||||||
using type2 = decltype(check2<T>(0));
|
|
||||||
|
|
||||||
public:
|
|
||||||
using type = std::integral_constant<bool,
|
|
||||||
type1::value && type2::value>;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // detail
|
|
||||||
} // beast
|
|
||||||
|
|
||||||
#endif
|
|
@@ -8,8 +8,8 @@
|
|||||||
#ifndef BEAST_DETAIL_SYNC_OSTREAM_HPP
|
#ifndef BEAST_DETAIL_SYNC_OSTREAM_HPP
|
||||||
#define BEAST_DETAIL_SYNC_OSTREAM_HPP
|
#define BEAST_DETAIL_SYNC_OSTREAM_HPP
|
||||||
|
|
||||||
#include <beast/core/buffer_concepts.hpp>
|
|
||||||
#include <beast/core/error.hpp>
|
#include <beast/core/error.hpp>
|
||||||
|
#include <beast/core/type_traits.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
|
@@ -8,6 +8,10 @@
|
|||||||
#ifndef BEAST_DETAIL_TYPE_TRAITS_HPP
|
#ifndef BEAST_DETAIL_TYPE_TRAITS_HPP
|
||||||
#define BEAST_DETAIL_TYPE_TRAITS_HPP
|
#define BEAST_DETAIL_TYPE_TRAITS_HPP
|
||||||
|
|
||||||
|
#include <beast/core/error.hpp>
|
||||||
|
#include <boost/asio/buffer.hpp>
|
||||||
|
#include <boost/asio/io_service.hpp>
|
||||||
|
#include <iterator>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
@@ -16,6 +20,10 @@
|
|||||||
namespace beast {
|
namespace beast {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
|
//
|
||||||
|
// utilities
|
||||||
|
//
|
||||||
|
|
||||||
template<class... Ts>
|
template<class... Ts>
|
||||||
struct make_void
|
struct make_void
|
||||||
{
|
{
|
||||||
@@ -160,6 +168,288 @@ struct get_lowest_layer
|
|||||||
has_lowest_layer<T>::value>::type;
|
has_lowest_layer<T>::value>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//
|
||||||
|
// buffer concepts
|
||||||
|
//
|
||||||
|
|
||||||
|
// Types that meet the requirements,
|
||||||
|
// for use with std::declval only.
|
||||||
|
template<class BufferType>
|
||||||
|
struct BufferSequence
|
||||||
|
{
|
||||||
|
using value_type = BufferType;
|
||||||
|
using const_iterator = BufferType const*;
|
||||||
|
~BufferSequence();
|
||||||
|
BufferSequence(BufferSequence const&) = default;
|
||||||
|
const_iterator begin() const noexcept;
|
||||||
|
const_iterator end() const noexcept;
|
||||||
|
};
|
||||||
|
using ConstBufferSequence =
|
||||||
|
BufferSequence<boost::asio::const_buffer>;
|
||||||
|
using MutableBufferSequence =
|
||||||
|
BufferSequence<boost::asio::mutable_buffer>;
|
||||||
|
|
||||||
|
template<class T, class BufferType>
|
||||||
|
class is_buffer_sequence
|
||||||
|
{
|
||||||
|
template<class U, class R = std::is_convertible<
|
||||||
|
typename U::value_type, BufferType> >
|
||||||
|
static R check1(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check1(...);
|
||||||
|
using type1 = decltype(check1<T>(0));
|
||||||
|
|
||||||
|
template<class U, class R = std::is_base_of<
|
||||||
|
#if 0
|
||||||
|
std::bidirectional_iterator_tag,
|
||||||
|
typename std::iterator_traits<
|
||||||
|
typename U::const_iterator>::iterator_category>>
|
||||||
|
#else
|
||||||
|
// workaround:
|
||||||
|
// boost::asio::detail::consuming_buffers::const_iterator
|
||||||
|
// is not bidirectional
|
||||||
|
std::forward_iterator_tag,
|
||||||
|
typename std::iterator_traits<
|
||||||
|
typename U::const_iterator>::iterator_category>>
|
||||||
|
#endif
|
||||||
|
static R check2(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check2(...);
|
||||||
|
using type2 = decltype(check2<T>(0));
|
||||||
|
|
||||||
|
template<class U, class R = typename
|
||||||
|
std::is_convertible<decltype(
|
||||||
|
std::declval<U>().begin()),
|
||||||
|
typename U::const_iterator>::type>
|
||||||
|
static R check3(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check3(...);
|
||||||
|
using type3 = decltype(check3<T>(0));
|
||||||
|
|
||||||
|
template<class U, class R = typename std::is_convertible<decltype(
|
||||||
|
std::declval<U>().end()),
|
||||||
|
typename U::const_iterator>::type>
|
||||||
|
static R check4(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check4(...);
|
||||||
|
using type4 = decltype(check4<T>(0));
|
||||||
|
|
||||||
|
public:
|
||||||
|
using type = std::integral_constant<bool,
|
||||||
|
std::is_copy_constructible<T>::value &&
|
||||||
|
std::is_destructible<T>::value &&
|
||||||
|
type1::value && type2::value &&
|
||||||
|
type3::value && type4::value>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class B1, class... Bn>
|
||||||
|
struct is_all_ConstBufferSequence
|
||||||
|
: std::integral_constant<bool,
|
||||||
|
is_buffer_sequence<B1, boost::asio::const_buffer>::type::value &&
|
||||||
|
is_all_ConstBufferSequence<Bn...>::value>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class B1>
|
||||||
|
struct is_all_ConstBufferSequence<B1>
|
||||||
|
: is_buffer_sequence<B1, boost::asio::const_buffer>::type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class is_dynamic_buffer
|
||||||
|
{
|
||||||
|
// size()
|
||||||
|
template<class U, class R = std::is_convertible<decltype(
|
||||||
|
std::declval<U const>().size()), std::size_t>>
|
||||||
|
static R check1(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check1(...);
|
||||||
|
using type1 = decltype(check1<T>(0));
|
||||||
|
|
||||||
|
// max_size()
|
||||||
|
template<class U, class R = std::is_convertible<decltype(
|
||||||
|
std::declval<U const>().max_size()), std::size_t>>
|
||||||
|
static R check2(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check2(...);
|
||||||
|
using type2 = decltype(check2<T>(0));
|
||||||
|
|
||||||
|
// capacity()
|
||||||
|
template<class U, class R = std::is_convertible<decltype(
|
||||||
|
std::declval<U const>().capacity()), std::size_t>>
|
||||||
|
static R check3(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check3(...);
|
||||||
|
using type3 = decltype(check3<T>(0));
|
||||||
|
|
||||||
|
// data()
|
||||||
|
template<class U, class R = std::integral_constant<
|
||||||
|
bool, is_buffer_sequence<decltype(
|
||||||
|
std::declval<U const>().data()),
|
||||||
|
boost::asio::const_buffer>::type::value>>
|
||||||
|
static R check4(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check4(...);
|
||||||
|
using type4 = decltype(check4<T>(0));
|
||||||
|
|
||||||
|
// prepare()
|
||||||
|
template<class U, class R = std::integral_constant<
|
||||||
|
bool, is_buffer_sequence<decltype(
|
||||||
|
std::declval<U>().prepare(1)),
|
||||||
|
boost::asio::mutable_buffer>::type::value>>
|
||||||
|
static R check5(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check5(...);
|
||||||
|
using type5 = decltype(check5<T>(0));
|
||||||
|
|
||||||
|
// commit()
|
||||||
|
template<class U, class R = decltype(
|
||||||
|
std::declval<U>().commit(1), std::true_type{})>
|
||||||
|
static R check6(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check6(...);
|
||||||
|
using type6 = decltype(check6<T>(0));
|
||||||
|
|
||||||
|
// consume
|
||||||
|
template<class U, class R = decltype(
|
||||||
|
std::declval<U>().consume(1), std::true_type{})>
|
||||||
|
static R check7(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check7(...);
|
||||||
|
using type7 = decltype(check7<T>(0));
|
||||||
|
|
||||||
|
public:
|
||||||
|
using type = std::integral_constant<bool,
|
||||||
|
type1::value
|
||||||
|
&& type2::value
|
||||||
|
//&& type3::value // Networking TS
|
||||||
|
&& type4::value
|
||||||
|
&& type5::value
|
||||||
|
&& type6::value
|
||||||
|
&& type7::value
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//
|
||||||
|
// stream concepts
|
||||||
|
//
|
||||||
|
|
||||||
|
// Types that meet the requirements,
|
||||||
|
// for use with std::declval only.
|
||||||
|
struct StreamHandler
|
||||||
|
{
|
||||||
|
StreamHandler(StreamHandler const&) = default;
|
||||||
|
void operator()(error_code ec, std::size_t);
|
||||||
|
};
|
||||||
|
using ReadHandler = StreamHandler;
|
||||||
|
using WriteHandler = StreamHandler;
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class has_get_io_service
|
||||||
|
{
|
||||||
|
template<class U, class R = typename std::is_same<
|
||||||
|
decltype(std::declval<U>().get_io_service()),
|
||||||
|
boost::asio::io_service&>>
|
||||||
|
static R check(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check(...);
|
||||||
|
public:
|
||||||
|
using type = decltype(check<T>(0));
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class is_async_read_stream
|
||||||
|
{
|
||||||
|
template<class U, class R = decltype(
|
||||||
|
std::declval<U>().async_read_some(
|
||||||
|
std::declval<MutableBufferSequence>(),
|
||||||
|
std::declval<ReadHandler>()),
|
||||||
|
std::true_type{})>
|
||||||
|
static R check(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check(...);
|
||||||
|
using type1 = decltype(check<T>(0));
|
||||||
|
public:
|
||||||
|
using type = std::integral_constant<bool,
|
||||||
|
type1::value &&
|
||||||
|
has_get_io_service<T>::type::value>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class is_async_write_stream
|
||||||
|
{
|
||||||
|
template<class U, class R = decltype(
|
||||||
|
std::declval<U>().async_write_some(
|
||||||
|
std::declval<ConstBufferSequence>(),
|
||||||
|
std::declval<WriteHandler>()),
|
||||||
|
std::true_type{})>
|
||||||
|
static R check(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check(...);
|
||||||
|
using type1 = decltype(check<T>(0));
|
||||||
|
public:
|
||||||
|
using type = std::integral_constant<bool,
|
||||||
|
type1::value &&
|
||||||
|
has_get_io_service<T>::type::value>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class is_sync_read_stream
|
||||||
|
{
|
||||||
|
template<class U, class R = std::is_same<decltype(
|
||||||
|
std::declval<U>().read_some(
|
||||||
|
std::declval<MutableBufferSequence>())),
|
||||||
|
std::size_t>>
|
||||||
|
static R check1(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check1(...);
|
||||||
|
using type1 = decltype(check1<T>(0));
|
||||||
|
|
||||||
|
template<class U, class R = std::is_same<decltype(
|
||||||
|
std::declval<U>().read_some(
|
||||||
|
std::declval<MutableBufferSequence>(),
|
||||||
|
std::declval<error_code&>())), std::size_t>>
|
||||||
|
static R check2(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check2(...);
|
||||||
|
using type2 = decltype(check2<T>(0));
|
||||||
|
|
||||||
|
public:
|
||||||
|
using type = std::integral_constant<bool,
|
||||||
|
type1::value && type2::value>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class is_sync_write_stream
|
||||||
|
{
|
||||||
|
template<class U, class R = std::is_same<decltype(
|
||||||
|
std::declval<U>().write_some(
|
||||||
|
std::declval<ConstBufferSequence>())),
|
||||||
|
std::size_t>>
|
||||||
|
static R check1(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check1(...);
|
||||||
|
using type1 = decltype(check1<T>(0));
|
||||||
|
|
||||||
|
template<class U, class R = std::is_same<decltype(
|
||||||
|
std::declval<U>().write_some(
|
||||||
|
std::declval<ConstBufferSequence>(),
|
||||||
|
std::declval<error_code&>())), std::size_t>>
|
||||||
|
static R check2(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check2(...);
|
||||||
|
using type2 = decltype(check2<T>(0));
|
||||||
|
|
||||||
|
public:
|
||||||
|
using type = std::integral_constant<bool,
|
||||||
|
type1::value && type2::value>;
|
||||||
|
};
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
} // beast
|
} // beast
|
||||||
|
|
||||||
|
@@ -1,28 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2013-2017 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_HANDLER_CONCEPTS_HPP
|
|
||||||
#define BEAST_HANDLER_CONCEPTS_HPP
|
|
||||||
|
|
||||||
#include <beast/config.hpp>
|
|
||||||
#include <beast/core/detail/type_traits.hpp>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
/// Determine if `T` meets the requirements of @b `CompletionHandler`.
|
|
||||||
template<class T, class Signature>
|
|
||||||
#if BEAST_DOXYGEN
|
|
||||||
using is_CompletionHandler = std::integral_constant<bool, ...>;
|
|
||||||
#else
|
|
||||||
using is_CompletionHandler = std::integral_constant<bool,
|
|
||||||
std::is_copy_constructible<typename std::decay<T>::type>::value &&
|
|
||||||
detail::is_invocable<T, Signature>::value>;
|
|
||||||
#endif
|
|
||||||
} // beast
|
|
||||||
|
|
||||||
#endif
|
|
@@ -191,6 +191,11 @@ public:
|
|||||||
deallocation-before-invocation Asio guarantee. All
|
deallocation-before-invocation Asio guarantee. All
|
||||||
instances of @ref handler_ptr which refer to the
|
instances of @ref handler_ptr which refer to the
|
||||||
same owned object will be reset, including this instance.
|
same owned object will be reset, including this instance.
|
||||||
|
|
||||||
|
@note Care must be taken when the arguments are themselves
|
||||||
|
stored in the owned object. Such arguments must first be
|
||||||
|
moved to the stack or elsewhere, and then passed, or else
|
||||||
|
undefined behavior will result.
|
||||||
*/
|
*/
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
void
|
void
|
||||||
|
@@ -10,9 +10,9 @@
|
|||||||
|
|
||||||
#include <beast/core/bind_handler.hpp>
|
#include <beast/core/bind_handler.hpp>
|
||||||
#include <beast/core/error.hpp>
|
#include <beast/core/error.hpp>
|
||||||
#include <beast/core/handler_concepts.hpp>
|
|
||||||
#include <beast/core/handler_helpers.hpp>
|
#include <beast/core/handler_helpers.hpp>
|
||||||
#include <beast/core/handler_ptr.hpp>
|
#include <beast/core/handler_ptr.hpp>
|
||||||
|
#include <beast/core/type_traits.hpp>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
@@ -164,12 +164,12 @@ async_write_some(ConstBufferSequence const& buffers,
|
|||||||
WriteHandler&& handler) ->
|
WriteHandler&& handler) ->
|
||||||
async_return_type<WriteHandler, void(error_code)>
|
async_return_type<WriteHandler, void(error_code)>
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncWriteStream<next_layer_type>::value,
|
static_assert(is_async_write_stream<next_layer_type>::value,
|
||||||
"AsyncWriteStream requirements not met");
|
"AsyncWriteStream requirements not met");
|
||||||
static_assert(is_const_buffer_sequence<
|
static_assert(is_const_buffer_sequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
"ConstBufferSequence requirements not met");
|
"ConstBufferSequence requirements not met");
|
||||||
static_assert(is_CompletionHandler<WriteHandler,
|
static_assert(is_completion_handler<WriteHandler,
|
||||||
void(error_code, std::size_t)>::value,
|
void(error_code, std::size_t)>::value,
|
||||||
"WriteHandler requirements not met");
|
"WriteHandler requirements not met");
|
||||||
return next_layer_.async_write_some(buffers,
|
return next_layer_.async_write_some(buffers,
|
||||||
@@ -183,7 +183,7 @@ buffered_read_stream<Stream, DynamicBuffer>::
|
|||||||
read_some(
|
read_some(
|
||||||
MutableBufferSequence const& buffers)
|
MutableBufferSequence const& buffers)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncReadStream<next_layer_type>::value,
|
static_assert(is_sync_read_stream<next_layer_type>::value,
|
||||||
"SyncReadStream requirements not met");
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_mutable_buffer_sequence<
|
static_assert(is_mutable_buffer_sequence<
|
||||||
MutableBufferSequence>::value,
|
MutableBufferSequence>::value,
|
||||||
@@ -202,7 +202,7 @@ buffered_read_stream<Stream, DynamicBuffer>::
|
|||||||
read_some(MutableBufferSequence const& buffers,
|
read_some(MutableBufferSequence const& buffers,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncReadStream<next_layer_type>::value,
|
static_assert(is_sync_read_stream<next_layer_type>::value,
|
||||||
"SyncReadStream requirements not met");
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_mutable_buffer_sequence<
|
static_assert(is_mutable_buffer_sequence<
|
||||||
MutableBufferSequence>::value,
|
MutableBufferSequence>::value,
|
||||||
@@ -232,7 +232,7 @@ async_read_some(MutableBufferSequence const& buffers,
|
|||||||
ReadHandler&& handler) ->
|
ReadHandler&& handler) ->
|
||||||
async_return_type<ReadHandler, void(error_code)>
|
async_return_type<ReadHandler, void(error_code)>
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncReadStream<next_layer_type>::value,
|
static_assert(is_async_read_stream<next_layer_type>::value,
|
||||||
"Stream requirements not met");
|
"Stream requirements not met");
|
||||||
static_assert(is_mutable_buffer_sequence<
|
static_assert(is_mutable_buffer_sequence<
|
||||||
MutableBufferSequence>::value,
|
MutableBufferSequence>::value,
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
#ifndef BEAST_IMPL_CONSUMING_BUFFERS_IPP
|
#ifndef BEAST_IMPL_CONSUMING_BUFFERS_IPP
|
||||||
#define BEAST_IMPL_CONSUMING_BUFFERS_IPP
|
#define BEAST_IMPL_CONSUMING_BUFFERS_IPP
|
||||||
|
|
||||||
#include <beast/core/buffer_concepts.hpp>
|
#include <beast/core/type_traits.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
/** A @b `DynamicBuffer` that uses multiple buffers internally.
|
/** A @b DynamicBuffer that uses multiple buffers internally.
|
||||||
|
|
||||||
The implementation uses a sequence of one or more character arrays
|
The implementation uses a sequence of one or more character arrays
|
||||||
of varying sizes. Additional character array objects are appended to
|
of varying sizes. Additional character array objects are appended to
|
||||||
@@ -315,15 +315,7 @@ private:
|
|||||||
debug_check() const;
|
debug_check() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A @b `DynamicBuffer` that uses multiple buffers internally.
|
/// A typical multi buffer
|
||||||
|
|
||||||
The implementation uses a sequence of one or more character arrays
|
|
||||||
of varying sizes. Additional character array objects are appended to
|
|
||||||
the sequence to accommodate changes in the size of the character
|
|
||||||
sequence.
|
|
||||||
|
|
||||||
@note Meets the requirements of @b `DynamicBuffer`.
|
|
||||||
*/
|
|
||||||
using multi_buffer = basic_multi_buffer<std::allocator<char>>;
|
using multi_buffer = basic_multi_buffer<std::allocator<char>>;
|
||||||
|
|
||||||
} // beast
|
} // beast
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
#define BEAST_WRITE_OSTREAM_HPP
|
#define BEAST_WRITE_OSTREAM_HPP
|
||||||
|
|
||||||
#include <beast/config.hpp>
|
#include <beast/config.hpp>
|
||||||
#include <beast/core/buffer_concepts.hpp>
|
#include <beast/core/type_traits.hpp>
|
||||||
#include <beast/core/detail/ostream.hpp>
|
#include <beast/core/detail/ostream.hpp>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <streambuf>
|
#include <streambuf>
|
||||||
@@ -35,6 +35,8 @@ namespace beast {
|
|||||||
|
|
||||||
@param b An object meeting the requirements of @b ConstBufferSequence
|
@param b An object meeting the requirements of @b ConstBufferSequence
|
||||||
to be streamed. The implementation will make a copy of this object.
|
to be streamed. The implementation will make a copy of this object.
|
||||||
|
Ownership of the underlying memory is not transferred, the application
|
||||||
|
is still responsible for managing its lifetime.
|
||||||
*/
|
*/
|
||||||
template<class ConstBufferSequence>
|
template<class ConstBufferSequence>
|
||||||
#if BEAST_DOXYGEN
|
#if BEAST_DOXYGEN
|
||||||
@@ -68,11 +70,12 @@ buffers(ConstBufferSequence const& b)
|
|||||||
@param buffer An object meeting the requirements of @b DynamicBuffer
|
@param buffer An object meeting the requirements of @b DynamicBuffer
|
||||||
into which the formatted output will be placed.
|
into which the formatted output will be placed.
|
||||||
|
|
||||||
@return An object derived from `std::ostream` which directs output
|
@return An object derived from `std::ostream` which redirects output
|
||||||
into the specified dynamic buffer. Ownership of the dynamic buffer
|
The wrapped dynamic buffer is not modified, a copy is made instead.
|
||||||
is not transferred. The caller is responsible for ensuring the
|
Ownership of the underlying memory is not transferred, the application
|
||||||
dynamic buffer is not destroyed for the lifetime of the output
|
is still responsible for managing its lifetime. The caller is
|
||||||
stream.
|
responsible for ensuring the dynamic buffer is not destroyed for the
|
||||||
|
lifetime of the output stream.
|
||||||
*/
|
*/
|
||||||
template<class DynamicBuffer>
|
template<class DynamicBuffer>
|
||||||
#if BEAST_DOXYGEN
|
#if BEAST_DOXYGEN
|
||||||
|
@@ -25,6 +25,11 @@ namespace beast {
|
|||||||
of template functions receiving static stream buffer arguments in a
|
of template functions receiving static stream buffer arguments in a
|
||||||
deduced context, the signature of the receiving function should use
|
deduced context, the signature of the receiving function should use
|
||||||
@ref static_buffer.
|
@ref static_buffer.
|
||||||
|
|
||||||
|
When used with @ref static_buffer_n this implements a dynamic
|
||||||
|
buffer using no memory allocations.
|
||||||
|
|
||||||
|
@see @ref static_buffer_n
|
||||||
*/
|
*/
|
||||||
class static_buffer
|
class static_buffer
|
||||||
{
|
{
|
||||||
@@ -141,11 +146,15 @@ protected:
|
|||||||
|
|
||||||
/** A @b DynamicBuffer with a fixed size internal buffer.
|
/** A @b DynamicBuffer with a fixed size internal buffer.
|
||||||
|
|
||||||
|
This implements a dynamic buffer using no memory allocations.
|
||||||
|
|
||||||
@tparam N The number of bytes in the internal buffer.
|
@tparam N The number of bytes in the internal buffer.
|
||||||
|
|
||||||
@note To reduce the number of template instantiations when passing
|
@note To reduce the number of template instantiations when passing
|
||||||
objects of this type in a deduced context, the signature of the
|
objects of this type in a deduced context, the signature of the
|
||||||
receiving function should use `static_buffer` instead.
|
receiving function should use @ref static_buffer instead.
|
||||||
|
|
||||||
|
@see @ref static_buffer
|
||||||
*/
|
*/
|
||||||
template<std::size_t N>
|
template<std::size_t N>
|
||||||
class static_buffer_n
|
class static_buffer_n
|
||||||
@@ -179,9 +188,10 @@ public:
|
|||||||
|
|
||||||
/** Reset the static buffer.
|
/** Reset the static buffer.
|
||||||
|
|
||||||
Postconditions:
|
@par Effects
|
||||||
The input sequence and output sequence are empty,
|
|
||||||
`max_size()` returns `N`.
|
The input sequence and output sequence are empty,
|
||||||
|
@ref max_size returns `N`.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
reset()
|
reset()
|
||||||
|
@@ -1,77 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2013-2017 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_STREAM_CONCEPTS_HPP
|
|
||||||
#define BEAST_STREAM_CONCEPTS_HPP
|
|
||||||
|
|
||||||
#include <beast/config.hpp>
|
|
||||||
#include <beast/core/detail/stream_concepts.hpp>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
/// Determine if `T` has the `get_io_service` member.
|
|
||||||
template<class T>
|
|
||||||
#if BEAST_DOXYGEN
|
|
||||||
struct has_get_io_service : std::integral_constant<bool, ...>{};
|
|
||||||
#else
|
|
||||||
using has_get_io_service = typename detail::has_get_io_service<T>::type;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// Determine if `T` meets the requirements of @b `AsyncReadStream`.
|
|
||||||
template<class T>
|
|
||||||
#if BEAST_DOXYGEN
|
|
||||||
struct is_AsyncReadStream : std::integral_constant<bool, ...>{};
|
|
||||||
#else
|
|
||||||
using is_AsyncReadStream = typename detail::is_AsyncReadStream<T>::type;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// Determine if `T` meets the requirements of @b `AsyncWriteStream`.
|
|
||||||
template<class T>
|
|
||||||
#if BEAST_DOXYGEN
|
|
||||||
struct is_AsyncWriteStream : std::integral_constant<bool, ...>{};
|
|
||||||
#else
|
|
||||||
using is_AsyncWriteStream = typename detail::is_AsyncWriteStream<T>::type;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// Determine if `T` meets the requirements of @b `SyncReadStream`.
|
|
||||||
template<class T>
|
|
||||||
#if BEAST_DOXYGEN
|
|
||||||
struct is_SyncReadStream : std::integral_constant<bool, ...>{};
|
|
||||||
#else
|
|
||||||
using is_SyncReadStream = typename detail::is_SyncReadStream<T>::type;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// Determine if `T` meets the requirements of @b `SyncWriterStream`.
|
|
||||||
template<class T>
|
|
||||||
#if BEAST_DOXYGEN
|
|
||||||
struct is_SyncWriteStream : std::integral_constant<bool, ...>{};
|
|
||||||
#else
|
|
||||||
using is_SyncWriteStream = typename detail::is_SyncWriteStream<T>::type;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// Determine if `T` meets the requirements of @b `AsyncStream`.
|
|
||||||
template<class T>
|
|
||||||
#if BEAST_DOXYGEN
|
|
||||||
struct is_AsyncStream : std::integral_constant<bool, ...>{};
|
|
||||||
#else
|
|
||||||
using is_AsyncStream = std::integral_constant<bool,
|
|
||||||
is_AsyncReadStream<T>::value && is_AsyncWriteStream<T>::value>;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// Determine if `T` meets the requirements of @b `SyncStream`.
|
|
||||||
template<class T>
|
|
||||||
#if BEAST_DOXYGEN
|
|
||||||
struct is_SyncStream : std::integral_constant<bool, ...>{};
|
|
||||||
#else
|
|
||||||
using is_SyncStream = std::integral_constant<bool,
|
|
||||||
is_SyncReadStream<T>::value && is_SyncWriteStream<T>::value>;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
|
|
||||||
#endif
|
|
123
include/beast/core/type_traits.hpp
Normal file
123
include/beast/core/type_traits.hpp
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2013-2017 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_TYPE_TRAITS_HPP
|
||||||
|
#define BEAST_TYPE_TRAITS_HPP
|
||||||
|
|
||||||
|
#include <beast/config.hpp>
|
||||||
|
#include <beast/core/detail/type_traits.hpp>
|
||||||
|
#include <boost/asio/buffer.hpp>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
|
||||||
|
/// Determine if `T` meets the requirements of @b ConstBufferSequence.
|
||||||
|
template<class T>
|
||||||
|
#if BEAST_DOXYGEN
|
||||||
|
struct is_const_buffer_sequence : std::integral_constant<bool, ...>
|
||||||
|
#else
|
||||||
|
struct is_const_buffer_sequence :
|
||||||
|
detail::is_buffer_sequence<T,
|
||||||
|
boost::asio::const_buffer>::type
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Determine if `T` meets the requirements of @b DynamicBuffer.
|
||||||
|
template<class T>
|
||||||
|
#if BEAST_DOXYGEN
|
||||||
|
struct is_dynamic_buffer : std::integral_constant<bool, ...>
|
||||||
|
#else
|
||||||
|
struct is_dynamic_buffer :
|
||||||
|
detail::is_dynamic_buffer<T>::type
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Determine if `T` meets the requirements of @b MutableBufferSequence.
|
||||||
|
template<class T>
|
||||||
|
#if BEAST_DOXYGEN
|
||||||
|
struct is_mutable_buffer_sequence : std::integral_constant<bool, ...>
|
||||||
|
#else
|
||||||
|
struct is_mutable_buffer_sequence :
|
||||||
|
detail::is_buffer_sequence<T,
|
||||||
|
boost::asio::mutable_buffer>::type
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Determine if `T` has the `get_io_service` member.
|
||||||
|
template<class T>
|
||||||
|
#if BEAST_DOXYGEN
|
||||||
|
struct has_get_io_service : std::integral_constant<bool, ...>{};
|
||||||
|
#else
|
||||||
|
using has_get_io_service = typename detail::has_get_io_service<T>::type;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Determine if `T` meets the requirements of @b AsyncReadStream.
|
||||||
|
template<class T>
|
||||||
|
#if BEAST_DOXYGEN
|
||||||
|
struct is_async_read_stream : std::integral_constant<bool, ...>{};
|
||||||
|
#else
|
||||||
|
using is_async_read_stream = typename detail::is_async_read_stream<T>::type;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Determine if `T` meets the requirements of @b AsyncWriteStream.
|
||||||
|
template<class T>
|
||||||
|
#if BEAST_DOXYGEN
|
||||||
|
struct is_async_write_stream : std::integral_constant<bool, ...>{};
|
||||||
|
#else
|
||||||
|
using is_async_write_stream = typename detail::is_async_write_stream<T>::type;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Determine if `T` meets the requirements of @b SyncReadStream.
|
||||||
|
template<class T>
|
||||||
|
#if BEAST_DOXYGEN
|
||||||
|
struct is_sync_read_stream : std::integral_constant<bool, ...>{};
|
||||||
|
#else
|
||||||
|
using is_sync_read_stream = typename detail::is_sync_read_stream<T>::type;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Determine if `T` meets the requirements of @b SyncWriterStream.
|
||||||
|
template<class T>
|
||||||
|
#if BEAST_DOXYGEN
|
||||||
|
struct is_sync_write_stream : std::integral_constant<bool, ...>{};
|
||||||
|
#else
|
||||||
|
using is_sync_write_stream = typename detail::is_sync_write_stream<T>::type;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Determine if `T` meets the requirements of @b AsyncStream.
|
||||||
|
template<class T>
|
||||||
|
#if BEAST_DOXYGEN
|
||||||
|
struct is_async_stream : std::integral_constant<bool, ...>{};
|
||||||
|
#else
|
||||||
|
using is_async_stream = std::integral_constant<bool,
|
||||||
|
is_async_read_stream<T>::value && is_async_write_stream<T>::value>;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Determine if `T` meets the requirements of @b SyncStream.
|
||||||
|
template<class T>
|
||||||
|
#if BEAST_DOXYGEN
|
||||||
|
struct is_sync_stream : std::integral_constant<bool, ...>{};
|
||||||
|
#else
|
||||||
|
using is_sync_stream = std::integral_constant<bool,
|
||||||
|
is_sync_read_stream<T>::value && is_sync_write_stream<T>::value>;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Determine if `T` meets the requirements of @b CompletionHandler.
|
||||||
|
template<class T, class Signature>
|
||||||
|
#if BEAST_DOXYGEN
|
||||||
|
using is_completion_handler = std::integral_constant<bool, ...>;
|
||||||
|
#else
|
||||||
|
using is_completion_handler = std::integral_constant<bool,
|
||||||
|
std::is_copy_constructible<typename std::decay<T>::type>::value &&
|
||||||
|
detail::is_invocable<T, Signature>::value>;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // beast
|
||||||
|
|
||||||
|
#endif
|
@@ -10,8 +10,7 @@
|
|||||||
|
|
||||||
#include <beast/config.hpp>
|
#include <beast/config.hpp>
|
||||||
#include <beast/core/error.hpp>
|
#include <beast/core/error.hpp>
|
||||||
#include <beast/core/buffer_concepts.hpp>
|
#include <beast/core/type_traits.hpp>
|
||||||
#include <beast/core/detail/type_traits.hpp>
|
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
@@ -16,9 +16,9 @@
|
|||||||
namespace beast {
|
namespace beast {
|
||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
/** A message body represented by a @b `DynamicBuffer`
|
/** A message body represented by a @b DynamicBuffer
|
||||||
|
|
||||||
Meets the requirements of @b `Body`.
|
Meets the requirements of @b Body.
|
||||||
*/
|
*/
|
||||||
template<class DynamicBuffer>
|
template<class DynamicBuffer>
|
||||||
struct basic_dynamic_body
|
struct basic_dynamic_body
|
||||||
@@ -113,7 +113,7 @@ private:
|
|||||||
|
|
||||||
/** A dynamic message body represented by a @ref multi_buffer
|
/** A dynamic message body represented by a @ref multi_buffer
|
||||||
|
|
||||||
Meets the requirements of @b `Body`.
|
Meets the requirements of @b Body.
|
||||||
*/
|
*/
|
||||||
using dynamic_body = basic_dynamic_body<multi_buffer>;
|
using dynamic_body = basic_dynamic_body<multi_buffer>;
|
||||||
|
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
#include <beast/core/bind_handler.hpp>
|
#include <beast/core/bind_handler.hpp>
|
||||||
#include <beast/core/handler_helpers.hpp>
|
#include <beast/core/handler_helpers.hpp>
|
||||||
#include <beast/core/handler_ptr.hpp>
|
#include <beast/core/handler_ptr.hpp>
|
||||||
#include <beast/core/stream_concepts.hpp>
|
#include <beast/core/type_traits.hpp>
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
@@ -645,7 +645,7 @@ async_read_some(
|
|||||||
basic_parser<isRequest, isDirect, Derived>& parser,
|
basic_parser<isRequest, isDirect, Derived>& parser,
|
||||||
ReadHandler&& handler)
|
ReadHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncReadStream<AsyncReadStream>::value,
|
static_assert(is_async_read_stream<AsyncReadStream>::value,
|
||||||
"AsyncReadStream requirements not met");
|
"AsyncReadStream requirements not met");
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
@@ -667,7 +667,7 @@ async_read(
|
|||||||
basic_parser<isRequest, isDirect, Derived>& parser,
|
basic_parser<isRequest, isDirect, Derived>& parser,
|
||||||
ReadHandler&& handler)
|
ReadHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncReadStream<AsyncReadStream>::value,
|
static_assert(is_async_read_stream<AsyncReadStream>::value,
|
||||||
"AsyncReadStream requirements not met");
|
"AsyncReadStream requirements not met");
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
@@ -694,7 +694,7 @@ async_read(
|
|||||||
message<isRequest, Body, Fields>& msg,
|
message<isRequest, Body, Fields>& msg,
|
||||||
ReadHandler&& handler)
|
ReadHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncReadStream<AsyncReadStream>::value,
|
static_assert(is_async_read_stream<AsyncReadStream>::value,
|
||||||
"AsyncReadStream requirements not met");
|
"AsyncReadStream requirements not met");
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
|
@@ -8,10 +8,9 @@
|
|||||||
#ifndef BEAST_HTTP_IMPL_BASIC_PARSER_IPP
|
#ifndef BEAST_HTTP_IMPL_BASIC_PARSER_IPP
|
||||||
#define BEAST_HTTP_IMPL_BASIC_PARSER_IPP
|
#define BEAST_HTTP_IMPL_BASIC_PARSER_IPP
|
||||||
|
|
||||||
#include <beast/core/buffer_concepts.hpp>
|
#include <beast/core/type_traits.hpp>
|
||||||
#include <beast/core/detail/ci_char_traits.hpp>
|
#include <beast/core/detail/ci_char_traits.hpp>
|
||||||
#include <beast/core/detail/clamp.hpp>
|
#include <beast/core/detail/clamp.hpp>
|
||||||
#include <beast/core/detail/type_traits.hpp>
|
|
||||||
#include <beast/http/error.hpp>
|
#include <beast/http/error.hpp>
|
||||||
#include <beast/http/rfc7230.hpp>
|
#include <beast/http/rfc7230.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
#include <beast/core/bind_handler.hpp>
|
#include <beast/core/bind_handler.hpp>
|
||||||
#include <beast/core/handler_helpers.hpp>
|
#include <beast/core/handler_helpers.hpp>
|
||||||
#include <beast/core/handler_ptr.hpp>
|
#include <beast/core/handler_ptr.hpp>
|
||||||
#include <beast/core/stream_concepts.hpp>
|
#include <beast/core/type_traits.hpp>
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
@@ -192,7 +192,7 @@ read_some(
|
|||||||
DynamicBuffer& dynabuf,
|
DynamicBuffer& dynabuf,
|
||||||
basic_parser<isRequest, isDirect, Derived>& parser)
|
basic_parser<isRequest, isDirect, Derived>& parser)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncReadStream<SyncReadStream>::value,
|
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
||||||
"SyncReadStream requirements not met");
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
@@ -216,7 +216,7 @@ read_some(
|
|||||||
basic_parser<isRequest, isDirect, Derived>& parser,
|
basic_parser<isRequest, isDirect, Derived>& parser,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncReadStream<SyncReadStream>::value,
|
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
||||||
"SyncReadStream requirements not met");
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
@@ -234,7 +234,7 @@ read(
|
|||||||
DynamicBuffer& dynabuf,
|
DynamicBuffer& dynabuf,
|
||||||
basic_parser<isRequest, isDirect, Derived>& parser)
|
basic_parser<isRequest, isDirect, Derived>& parser)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncReadStream<SyncReadStream>::value,
|
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
||||||
"SyncReadStream requirements not met");
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
@@ -256,7 +256,7 @@ read(
|
|||||||
basic_parser<isRequest, isDirect, Derived>& parser,
|
basic_parser<isRequest, isDirect, Derived>& parser,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncReadStream<SyncReadStream>::value,
|
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
||||||
"SyncReadStream requirements not met");
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
@@ -282,7 +282,7 @@ read(
|
|||||||
DynamicBuffer& dynabuf,
|
DynamicBuffer& dynabuf,
|
||||||
message<isRequest, Body, Fields>& msg)
|
message<isRequest, Body, Fields>& msg)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncReadStream<SyncReadStream>::value,
|
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
||||||
"SyncReadStream requirements not met");
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
@@ -310,7 +310,7 @@ read(
|
|||||||
message<isRequest, Body, Fields>& msg,
|
message<isRequest, Body, Fields>& msg,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncReadStream<SyncReadStream>::value,
|
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
||||||
"SyncReadStream requirements not met");
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
|
@@ -12,12 +12,11 @@
|
|||||||
#include <beast/http/chunk_encode.hpp>
|
#include <beast/http/chunk_encode.hpp>
|
||||||
#include <beast/core/buffer_cat.hpp>
|
#include <beast/core/buffer_cat.hpp>
|
||||||
#include <beast/core/bind_handler.hpp>
|
#include <beast/core/bind_handler.hpp>
|
||||||
#include <beast/core/buffer_concepts.hpp>
|
|
||||||
#include <beast/core/ostream.hpp>
|
#include <beast/core/ostream.hpp>
|
||||||
#include <beast/core/handler_helpers.hpp>
|
#include <beast/core/handler_helpers.hpp>
|
||||||
#include <beast/core/handler_ptr.hpp>
|
#include <beast/core/handler_ptr.hpp>
|
||||||
#include <beast/core/stream_concepts.hpp>
|
|
||||||
#include <beast/core/multi_buffer.hpp>
|
#include <beast/core/multi_buffer.hpp>
|
||||||
|
#include <beast/core/type_traits.hpp>
|
||||||
#include <beast/core/detail/sync_ostream.hpp>
|
#include <beast/core/detail/sync_ostream.hpp>
|
||||||
#include <boost/asio/write.hpp>
|
#include <boost/asio/write.hpp>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
@@ -183,7 +182,7 @@ void
|
|||||||
write(SyncWriteStream& stream,
|
write(SyncWriteStream& stream,
|
||||||
header<isRequest, Fields> const& msg)
|
header<isRequest, Fields> const& msg)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncWriteStream<SyncWriteStream>::value,
|
static_assert(is_sync_write_stream<SyncWriteStream>::value,
|
||||||
"SyncWriteStream requirements not met");
|
"SyncWriteStream requirements not met");
|
||||||
error_code ec;
|
error_code ec;
|
||||||
write(stream, msg, ec);
|
write(stream, msg, ec);
|
||||||
@@ -198,7 +197,7 @@ write(SyncWriteStream& stream,
|
|||||||
header<isRequest, Fields> const& msg,
|
header<isRequest, Fields> const& msg,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncWriteStream<SyncWriteStream>::value,
|
static_assert(is_sync_write_stream<SyncWriteStream>::value,
|
||||||
"SyncWriteStream requirements not met");
|
"SyncWriteStream requirements not met");
|
||||||
multi_buffer b;
|
multi_buffer b;
|
||||||
{
|
{
|
||||||
@@ -219,7 +218,7 @@ async_write(AsyncWriteStream& stream,
|
|||||||
header<isRequest, Fields> const& msg,
|
header<isRequest, Fields> const& msg,
|
||||||
WriteHandler&& handler)
|
WriteHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncWriteStream<AsyncWriteStream>::value,
|
static_assert(is_async_write_stream<AsyncWriteStream>::value,
|
||||||
"AsyncWriteStream requirements not met");
|
"AsyncWriteStream requirements not met");
|
||||||
async_completion<WriteHandler,
|
async_completion<WriteHandler,
|
||||||
void(error_code)> init{handler};
|
void(error_code)> init{handler};
|
||||||
@@ -565,7 +564,7 @@ void
|
|||||||
write(SyncWriteStream& stream,
|
write(SyncWriteStream& stream,
|
||||||
message<isRequest, Body, Fields> const& msg)
|
message<isRequest, Body, Fields> const& msg)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncWriteStream<SyncWriteStream>::value,
|
static_assert(is_sync_write_stream<SyncWriteStream>::value,
|
||||||
"SyncWriteStream requirements not met");
|
"SyncWriteStream requirements not met");
|
||||||
static_assert(is_Body<Body>::value,
|
static_assert(is_Body<Body>::value,
|
||||||
"Body requirements not met");
|
"Body requirements not met");
|
||||||
@@ -587,7 +586,7 @@ write(SyncWriteStream& stream,
|
|||||||
message<isRequest, Body, Fields> const& msg,
|
message<isRequest, Body, Fields> const& msg,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncWriteStream<SyncWriteStream>::value,
|
static_assert(is_sync_write_stream<SyncWriteStream>::value,
|
||||||
"SyncWriteStream requirements not met");
|
"SyncWriteStream requirements not met");
|
||||||
static_assert(is_Body<Body>::value,
|
static_assert(is_Body<Body>::value,
|
||||||
"Body requirements not met");
|
"Body requirements not met");
|
||||||
@@ -647,7 +646,7 @@ async_write(AsyncWriteStream& stream,
|
|||||||
message<isRequest, Body, Fields> const& msg,
|
message<isRequest, Body, Fields> const& msg,
|
||||||
WriteHandler&& handler)
|
WriteHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncWriteStream<AsyncWriteStream>::value,
|
static_assert(is_async_write_stream<AsyncWriteStream>::value,
|
||||||
"AsyncWriteStream requirements not met");
|
"AsyncWriteStream requirements not met");
|
||||||
static_assert(is_Body<Body>::value,
|
static_assert(is_Body<Body>::value,
|
||||||
"Body requirements not met");
|
"Body requirements not met");
|
||||||
|
@@ -374,9 +374,9 @@ async_read(
|
|||||||
@ref error::end_of_stream is indicated.
|
@ref error::end_of_stream is indicated.
|
||||||
|
|
||||||
@param stream The stream from which the data is to be read.
|
@param stream The stream from which the data is to be read.
|
||||||
The type must support the @b `SyncReadStream` concept.
|
The type must support the @b SyncReadStream concept.
|
||||||
|
|
||||||
@param dynabuf A @b `DynamicBuffer` holding additional bytes
|
@param dynabuf A @b DynamicBuffer holding additional bytes
|
||||||
read by the implementation from the stream. This is both
|
read by the implementation from the stream. This is both
|
||||||
an input and an output parameter; on entry, any data in the
|
an input and an output parameter; on entry, any data in the
|
||||||
dynamic buffer's input sequence will be given to the parser
|
dynamic buffer's input sequence will be given to the parser
|
||||||
@@ -420,9 +420,9 @@ read(
|
|||||||
@ref error::end_of_stream is indicated.
|
@ref error::end_of_stream is indicated.
|
||||||
|
|
||||||
@param stream The stream from which the data is to be read.
|
@param stream The stream from which the data is to be read.
|
||||||
The type must support the @b `SyncReadStream` concept.
|
The type must support the @b SyncReadStream concept.
|
||||||
|
|
||||||
@param dynabuf A @b `DynamicBuffer` holding additional bytes
|
@param dynabuf A @b DynamicBuffer holding additional bytes
|
||||||
read by the implementation from the stream. This is both
|
read by the implementation from the stream. This is both
|
||||||
an input and an output parameter; on entry, any data in the
|
an input and an output parameter; on entry, any data in the
|
||||||
dynamic buffer's input sequence will be given to the parser
|
dynamic buffer's input sequence will be given to the parser
|
||||||
@@ -470,9 +470,9 @@ read(
|
|||||||
@ref error::end_of_stream is indicated.
|
@ref error::end_of_stream is indicated.
|
||||||
|
|
||||||
@param stream The stream to read the message from.
|
@param stream The stream to read the message from.
|
||||||
The type must support the @b `AsyncReadStream` concept.
|
The type must support the @b AsyncReadStream concept.
|
||||||
|
|
||||||
@param dynabuf A @b `DynamicBuffer` holding additional bytes
|
@param dynabuf A @b DynamicBuffer holding additional bytes
|
||||||
read by the implementation from the stream. This is both
|
read by the implementation from the stream. This is both
|
||||||
an input and an output parameter; on entry, any data in the
|
an input and an output parameter; on entry, any data in the
|
||||||
dynamic buffer's input sequence will be given to the parser
|
dynamic buffer's input sequence will be given to the parser
|
||||||
|
@@ -21,7 +21,7 @@ namespace http {
|
|||||||
|
|
||||||
/** A Body represented by a std::string.
|
/** A Body represented by a std::string.
|
||||||
|
|
||||||
Meets the requirements of @b `Body`.
|
Meets the requirements of @b Body.
|
||||||
*/
|
*/
|
||||||
struct string_body
|
struct string_body
|
||||||
{
|
{
|
||||||
|
@@ -36,7 +36,7 @@ namespace http {
|
|||||||
this function will not return `boost::asio::error::eof`.
|
this function will not return `boost::asio::error::eof`.
|
||||||
|
|
||||||
@param stream The stream to which the data is to be written.
|
@param stream The stream to which the data is to be written.
|
||||||
The type must support the @b `SyncWriteStream` concept.
|
The type must support the @b SyncWriteStream concept.
|
||||||
|
|
||||||
@param msg The header to write.
|
@param msg The header to write.
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ write(SyncWriteStream& stream,
|
|||||||
this function will not return `boost::asio::error::eof`.
|
this function will not return `boost::asio::error::eof`.
|
||||||
|
|
||||||
@param stream The stream to which the data is to be written.
|
@param stream The stream to which the data is to be written.
|
||||||
The type must support the @b `SyncWriteStream` concept.
|
The type must support the @b SyncWriteStream concept.
|
||||||
|
|
||||||
@param msg The header to write.
|
@param msg The header to write.
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ write(SyncWriteStream& stream,
|
|||||||
this function will not return `boost::asio::error::eof`.
|
this function will not return `boost::asio::error::eof`.
|
||||||
|
|
||||||
@param stream The stream to which the data is to be written.
|
@param stream The stream to which the data is to be written.
|
||||||
The type must support the @b `AsyncWriteStream` concept.
|
The type must support the @b AsyncWriteStream concept.
|
||||||
|
|
||||||
@param msg The header to write. The object must remain valid
|
@param msg The header to write. The object must remain valid
|
||||||
at least until the completion handler is called; ownership is
|
at least until the completion handler is called; ownership is
|
||||||
@@ -148,7 +148,7 @@ async_write(AsyncWriteStream& stream,
|
|||||||
function will be `boost::asio::error::eof`.
|
function will be `boost::asio::error::eof`.
|
||||||
|
|
||||||
@param stream The stream to which the data is to be written.
|
@param stream The stream to which the data is to be written.
|
||||||
The type must support the @b `SyncWriteStream` concept.
|
The type must support the @b SyncWriteStream concept.
|
||||||
|
|
||||||
@param msg The message to write.
|
@param msg The message to write.
|
||||||
|
|
||||||
@@ -179,7 +179,7 @@ write(SyncWriteStream& stream,
|
|||||||
function will be `boost::asio::error::eof`.
|
function will be `boost::asio::error::eof`.
|
||||||
|
|
||||||
@param stream The stream to which the data is to be written.
|
@param stream The stream to which the data is to be written.
|
||||||
The type must support the @b `SyncWriteStream` concept.
|
The type must support the @b SyncWriteStream concept.
|
||||||
|
|
||||||
@param msg The message to write.
|
@param msg The message to write.
|
||||||
|
|
||||||
@@ -216,7 +216,7 @@ write(SyncWriteStream& stream,
|
|||||||
the error set to `boost::asio::error::eof`.
|
the error set to `boost::asio::error::eof`.
|
||||||
|
|
||||||
@param stream The stream to which the data is to be written.
|
@param stream The stream to which the data is to be written.
|
||||||
The type must support the @b `AsyncWriteStream` concept.
|
The type must support the @b AsyncWriteStream concept.
|
||||||
|
|
||||||
@param msg The message to write. The object must remain valid
|
@param msg The message to write. The object must remain valid
|
||||||
at least until the completion handler is called; ownership is
|
at least until the completion handler is called; ownership is
|
||||||
|
@@ -8,9 +8,9 @@
|
|||||||
#ifndef BEAST_WEBSOCKET_DETAIL_UTF8_CHECKER_HPP
|
#ifndef BEAST_WEBSOCKET_DETAIL_UTF8_CHECKER_HPP
|
||||||
#define BEAST_WEBSOCKET_DETAIL_UTF8_CHECKER_HPP
|
#define BEAST_WEBSOCKET_DETAIL_UTF8_CHECKER_HPP
|
||||||
|
|
||||||
|
#include <beast/core/type_traits.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <beast/core/buffer_concepts.hpp>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
@@ -105,7 +105,8 @@ public:
|
|||||||
|
|
||||||
template<class _>
|
template<class _>
|
||||||
void
|
void
|
||||||
utf8_checker_t<_>::reset()
|
utf8_checker_t<_>::
|
||||||
|
reset()
|
||||||
{
|
{
|
||||||
need_ = 0;
|
need_ = 0;
|
||||||
p_ = have_;
|
p_ = have_;
|
||||||
@@ -113,7 +114,8 @@ utf8_checker_t<_>::reset()
|
|||||||
|
|
||||||
template<class _>
|
template<class _>
|
||||||
bool
|
bool
|
||||||
utf8_checker_t<_>::finish()
|
utf8_checker_t<_>::
|
||||||
|
finish()
|
||||||
{
|
{
|
||||||
auto const success = need_ == 0;
|
auto const success = need_ == 0;
|
||||||
reset();
|
reset();
|
||||||
@@ -123,7 +125,8 @@ utf8_checker_t<_>::finish()
|
|||||||
template<class _>
|
template<class _>
|
||||||
template<class ConstBufferSequence>
|
template<class ConstBufferSequence>
|
||||||
bool
|
bool
|
||||||
utf8_checker_t<_>::write(ConstBufferSequence const& bs)
|
utf8_checker_t<_>::
|
||||||
|
write(ConstBufferSequence const& bs)
|
||||||
{
|
{
|
||||||
static_assert(is_const_buffer_sequence<ConstBufferSequence>::value,
|
static_assert(is_const_buffer_sequence<ConstBufferSequence>::value,
|
||||||
"ConstBufferSequence requirements not met");
|
"ConstBufferSequence requirements not met");
|
||||||
@@ -138,7 +141,8 @@ utf8_checker_t<_>::write(ConstBufferSequence const& bs)
|
|||||||
|
|
||||||
template<class _>
|
template<class _>
|
||||||
bool
|
bool
|
||||||
utf8_checker_t<_>::write(std::uint8_t const* in, std::size_t size)
|
utf8_checker_t<_>::
|
||||||
|
write(std::uint8_t const* in, std::size_t size)
|
||||||
{
|
{
|
||||||
auto const valid =
|
auto const valid =
|
||||||
[](std::uint8_t const*& in)
|
[](std::uint8_t const*& in)
|
||||||
|
@@ -301,7 +301,7 @@ void
|
|||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
accept()
|
accept()
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
error_code ec;
|
error_code ec;
|
||||||
accept(ec);
|
accept(ec);
|
||||||
@@ -315,7 +315,7 @@ void
|
|||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
accept_ex(ResponseDecorator const& decorator)
|
accept_ex(ResponseDecorator const& decorator)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(detail::is_ResponseDecorator<
|
static_assert(detail::is_ResponseDecorator<
|
||||||
ResponseDecorator>::value,
|
ResponseDecorator>::value,
|
||||||
@@ -331,7 +331,7 @@ void
|
|||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
accept(error_code& ec)
|
accept(error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
reset();
|
reset();
|
||||||
do_accept(&default_decorate_res, ec);
|
do_accept(&default_decorate_res, ec);
|
||||||
@@ -343,7 +343,7 @@ void
|
|||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
accept_ex(ResponseDecorator const& decorator, error_code& ec)
|
accept_ex(ResponseDecorator const& decorator, error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(detail::is_ResponseDecorator<
|
static_assert(detail::is_ResponseDecorator<
|
||||||
ResponseDecorator>::value,
|
ResponseDecorator>::value,
|
||||||
@@ -358,7 +358,7 @@ void
|
|||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
accept(ConstBufferSequence const& buffers)
|
accept(ConstBufferSequence const& buffers)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(is_const_buffer_sequence<
|
static_assert(is_const_buffer_sequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
@@ -377,7 +377,7 @@ stream<NextLayer>::
|
|||||||
accept_ex(ConstBufferSequence const& buffers,
|
accept_ex(ConstBufferSequence const& buffers,
|
||||||
ResponseDecorator const &decorator)
|
ResponseDecorator const &decorator)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(is_const_buffer_sequence<
|
static_assert(is_const_buffer_sequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
@@ -397,7 +397,7 @@ void
|
|||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
accept(ConstBufferSequence const& buffers, error_code& ec)
|
accept(ConstBufferSequence const& buffers, error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(is_const_buffer_sequence<
|
static_assert(is_const_buffer_sequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
@@ -419,7 +419,7 @@ stream<NextLayer>::
|
|||||||
accept_ex(ConstBufferSequence const& buffers,
|
accept_ex(ConstBufferSequence const& buffers,
|
||||||
ResponseDecorator const& decorator, error_code& ec)
|
ResponseDecorator const& decorator, error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(is_const_buffer_sequence<
|
static_assert(is_const_buffer_sequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
@@ -442,7 +442,7 @@ void
|
|||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
accept(http::header<true, Fields> const& req)
|
accept(http::header<true, Fields> const& req)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
error_code ec;
|
error_code ec;
|
||||||
accept(req, ec);
|
accept(req, ec);
|
||||||
@@ -457,7 +457,7 @@ stream<NextLayer>::
|
|||||||
accept_ex(http::header<true, Fields> const& req,
|
accept_ex(http::header<true, Fields> const& req,
|
||||||
ResponseDecorator const& decorator)
|
ResponseDecorator const& decorator)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(detail::is_ResponseDecorator<
|
static_assert(detail::is_ResponseDecorator<
|
||||||
ResponseDecorator>::value,
|
ResponseDecorator>::value,
|
||||||
@@ -475,7 +475,7 @@ stream<NextLayer>::
|
|||||||
accept(http::header<true, Fields> const& req,
|
accept(http::header<true, Fields> const& req,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
reset();
|
reset();
|
||||||
do_accept(req, &default_decorate_res, ec);
|
do_accept(req, &default_decorate_res, ec);
|
||||||
@@ -488,7 +488,7 @@ stream<NextLayer>::
|
|||||||
accept_ex(http::header<true, Fields> const& req,
|
accept_ex(http::header<true, Fields> const& req,
|
||||||
ResponseDecorator const& decorator, error_code& ec)
|
ResponseDecorator const& decorator, error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(detail::is_ResponseDecorator<
|
static_assert(detail::is_ResponseDecorator<
|
||||||
ResponseDecorator>::value,
|
ResponseDecorator>::value,
|
||||||
@@ -504,7 +504,7 @@ stream<NextLayer>::
|
|||||||
accept(http::header<true, Fields> const& req,
|
accept(http::header<true, Fields> const& req,
|
||||||
ConstBufferSequence const& buffers)
|
ConstBufferSequence const& buffers)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(is_const_buffer_sequence<
|
static_assert(is_const_buffer_sequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
@@ -524,7 +524,7 @@ accept_ex(http::header<true, Fields> const& req,
|
|||||||
ConstBufferSequence const& buffers,
|
ConstBufferSequence const& buffers,
|
||||||
ResponseDecorator const& decorator)
|
ResponseDecorator const& decorator)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(is_const_buffer_sequence<
|
static_assert(is_const_buffer_sequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
@@ -545,7 +545,7 @@ stream<NextLayer>::
|
|||||||
accept(http::header<true, Fields> const& req,
|
accept(http::header<true, Fields> const& req,
|
||||||
ConstBufferSequence const& buffers, error_code& ec)
|
ConstBufferSequence const& buffers, error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(is_const_buffer_sequence<
|
static_assert(is_const_buffer_sequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
@@ -569,7 +569,7 @@ accept_ex(http::header<true, Fields> const& req,
|
|||||||
ResponseDecorator const& decorator,
|
ResponseDecorator const& decorator,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(is_const_buffer_sequence<
|
static_assert(is_const_buffer_sequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
@@ -595,7 +595,7 @@ async_return_type<
|
|||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
async_accept(AcceptHandler&& handler)
|
async_accept(AcceptHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
"AsyncStream requirements requirements not met");
|
"AsyncStream requirements requirements not met");
|
||||||
async_completion<AcceptHandler,
|
async_completion<AcceptHandler,
|
||||||
void(error_code)> init{handler};
|
void(error_code)> init{handler};
|
||||||
@@ -614,7 +614,7 @@ stream<NextLayer>::
|
|||||||
async_accept_ex(ResponseDecorator const& decorator,
|
async_accept_ex(ResponseDecorator const& decorator,
|
||||||
AcceptHandler&& handler)
|
AcceptHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
"AsyncStream requirements requirements not met");
|
"AsyncStream requirements requirements not met");
|
||||||
static_assert(detail::is_ResponseDecorator<
|
static_assert(detail::is_ResponseDecorator<
|
||||||
ResponseDecorator>::value,
|
ResponseDecorator>::value,
|
||||||
@@ -636,7 +636,7 @@ stream<NextLayer>::
|
|||||||
async_accept(ConstBufferSequence const& buffers,
|
async_accept(ConstBufferSequence const& buffers,
|
||||||
AcceptHandler&& handler)
|
AcceptHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
"AsyncStream requirements requirements not met");
|
"AsyncStream requirements requirements not met");
|
||||||
static_assert(is_const_buffer_sequence<
|
static_assert(is_const_buffer_sequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
@@ -660,7 +660,7 @@ async_accept_ex(ConstBufferSequence const& buffers,
|
|||||||
ResponseDecorator const& decorator,
|
ResponseDecorator const& decorator,
|
||||||
AcceptHandler&& handler)
|
AcceptHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
"AsyncStream requirements requirements not met");
|
"AsyncStream requirements requirements not met");
|
||||||
static_assert(is_const_buffer_sequence<
|
static_assert(is_const_buffer_sequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
@@ -685,7 +685,7 @@ stream<NextLayer>::
|
|||||||
async_accept(http::header<true, Fields> const& req,
|
async_accept(http::header<true, Fields> const& req,
|
||||||
AcceptHandler&& handler)
|
AcceptHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
"AsyncStream requirements requirements not met");
|
"AsyncStream requirements requirements not met");
|
||||||
async_completion<AcceptHandler,
|
async_completion<AcceptHandler,
|
||||||
void(error_code)> init{handler};
|
void(error_code)> init{handler};
|
||||||
@@ -707,7 +707,7 @@ stream<NextLayer>::
|
|||||||
async_accept_ex(http::header<true, Fields> const& req,
|
async_accept_ex(http::header<true, Fields> const& req,
|
||||||
ResponseDecorator const& decorator, AcceptHandler&& handler)
|
ResponseDecorator const& decorator, AcceptHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
"AsyncStream requirements requirements not met");
|
"AsyncStream requirements requirements not met");
|
||||||
static_assert(detail::is_ResponseDecorator<
|
static_assert(detail::is_ResponseDecorator<
|
||||||
ResponseDecorator>::value,
|
ResponseDecorator>::value,
|
||||||
@@ -733,7 +733,7 @@ async_accept(http::header<true, Fields> const& req,
|
|||||||
ConstBufferSequence const& buffers,
|
ConstBufferSequence const& buffers,
|
||||||
AcceptHandler&& handler)
|
AcceptHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
"AsyncStream requirements requirements not met");
|
"AsyncStream requirements requirements not met");
|
||||||
static_assert(is_const_buffer_sequence<
|
static_assert(is_const_buffer_sequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
@@ -760,7 +760,7 @@ async_accept_ex(http::header<true, Fields> const& req,
|
|||||||
ResponseDecorator const& decorator,
|
ResponseDecorator const& decorator,
|
||||||
AcceptHandler&& handler)
|
AcceptHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
"AsyncStream requirements requirements not met");
|
"AsyncStream requirements requirements not met");
|
||||||
static_assert(is_const_buffer_sequence<
|
static_assert(is_const_buffer_sequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
#include <beast/core/handler_helpers.hpp>
|
#include <beast/core/handler_helpers.hpp>
|
||||||
#include <beast/core/handler_ptr.hpp>
|
#include <beast/core/handler_ptr.hpp>
|
||||||
#include <beast/core/static_buffer.hpp>
|
#include <beast/core/static_buffer.hpp>
|
||||||
#include <beast/core/stream_concepts.hpp>
|
#include <beast/core/type_traits.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
@@ -202,7 +202,7 @@ async_return_type<
|
|||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
async_close(close_reason const& cr, CloseHandler&& handler)
|
async_close(close_reason const& cr, CloseHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
"AsyncStream requirements not met");
|
"AsyncStream requirements not met");
|
||||||
async_completion<CloseHandler,
|
async_completion<CloseHandler,
|
||||||
void(error_code)> init{handler};
|
void(error_code)> init{handler};
|
||||||
@@ -217,7 +217,7 @@ void
|
|||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
close(close_reason const& cr)
|
close(close_reason const& cr)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
error_code ec;
|
error_code ec;
|
||||||
close(cr, ec);
|
close(cr, ec);
|
||||||
@@ -230,7 +230,7 @@ void
|
|||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
close(close_reason const& cr, error_code& ec)
|
close(close_reason const& cr, error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
BOOST_ASSERT(! wr_close_);
|
BOOST_ASSERT(! wr_close_);
|
||||||
wr_close_ = true;
|
wr_close_ = true;
|
||||||
|
@@ -14,7 +14,7 @@
|
|||||||
#include <beast/http/write.hpp>
|
#include <beast/http/write.hpp>
|
||||||
#include <beast/core/handler_helpers.hpp>
|
#include <beast/core/handler_helpers.hpp>
|
||||||
#include <beast/core/handler_ptr.hpp>
|
#include <beast/core/handler_ptr.hpp>
|
||||||
#include <beast/core/stream_concepts.hpp>
|
#include <beast/core/type_traits.hpp>
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ async_handshake(string_view const& host,
|
|||||||
string_view const& target,
|
string_view const& target,
|
||||||
HandshakeHandler&& handler)
|
HandshakeHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
"AsyncStream requirements not met");
|
"AsyncStream requirements not met");
|
||||||
async_completion<HandshakeHandler,
|
async_completion<HandshakeHandler,
|
||||||
void(error_code)> init{handler};
|
void(error_code)> init{handler};
|
||||||
@@ -188,7 +188,7 @@ async_handshake(response_type& res,
|
|||||||
string_view const& target,
|
string_view const& target,
|
||||||
HandshakeHandler&& handler)
|
HandshakeHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
"AsyncStream requirements not met");
|
"AsyncStream requirements not met");
|
||||||
async_completion<HandshakeHandler,
|
async_completion<HandshakeHandler,
|
||||||
void(error_code)> init{handler};
|
void(error_code)> init{handler};
|
||||||
@@ -209,7 +209,7 @@ async_handshake_ex(string_view const& host,
|
|||||||
RequestDecorator const& decorator,
|
RequestDecorator const& decorator,
|
||||||
HandshakeHandler&& handler)
|
HandshakeHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
"AsyncStream requirements not met");
|
"AsyncStream requirements not met");
|
||||||
static_assert(detail::is_RequestDecorator<
|
static_assert(detail::is_RequestDecorator<
|
||||||
RequestDecorator>::value,
|
RequestDecorator>::value,
|
||||||
@@ -234,7 +234,7 @@ async_handshake_ex(response_type& res,
|
|||||||
RequestDecorator const& decorator,
|
RequestDecorator const& decorator,
|
||||||
HandshakeHandler&& handler)
|
HandshakeHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
"AsyncStream requirements not met");
|
"AsyncStream requirements not met");
|
||||||
static_assert(detail::is_RequestDecorator<
|
static_assert(detail::is_RequestDecorator<
|
||||||
RequestDecorator>::value,
|
RequestDecorator>::value,
|
||||||
@@ -254,7 +254,7 @@ stream<NextLayer>::
|
|||||||
handshake(string_view const& host,
|
handshake(string_view const& host,
|
||||||
string_view const& target)
|
string_view const& target)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
error_code ec;
|
error_code ec;
|
||||||
handshake(
|
handshake(
|
||||||
@@ -270,7 +270,7 @@ handshake(response_type& res,
|
|||||||
string_view const& host,
|
string_view const& host,
|
||||||
string_view const& target)
|
string_view const& target)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
error_code ec;
|
error_code ec;
|
||||||
handshake(res, host, target, ec);
|
handshake(res, host, target, ec);
|
||||||
@@ -286,7 +286,7 @@ handshake_ex(string_view const& host,
|
|||||||
string_view const& target,
|
string_view const& target,
|
||||||
RequestDecorator const& decorator)
|
RequestDecorator const& decorator)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(detail::is_RequestDecorator<
|
static_assert(detail::is_RequestDecorator<
|
||||||
RequestDecorator>::value,
|
RequestDecorator>::value,
|
||||||
@@ -306,7 +306,7 @@ handshake_ex(response_type& res,
|
|||||||
string_view const& target,
|
string_view const& target,
|
||||||
RequestDecorator const& decorator)
|
RequestDecorator const& decorator)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(detail::is_RequestDecorator<
|
static_assert(detail::is_RequestDecorator<
|
||||||
RequestDecorator>::value,
|
RequestDecorator>::value,
|
||||||
@@ -323,7 +323,7 @@ stream<NextLayer>::
|
|||||||
handshake(string_view const& host,
|
handshake(string_view const& host,
|
||||||
string_view const& target, error_code& ec)
|
string_view const& target, error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
do_handshake(nullptr,
|
do_handshake(nullptr,
|
||||||
host, target, &default_decorate_req, ec);
|
host, target, &default_decorate_req, ec);
|
||||||
@@ -337,7 +337,7 @@ handshake(response_type& res,
|
|||||||
string_view const& target,
|
string_view const& target,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
do_handshake(&res,
|
do_handshake(&res,
|
||||||
host, target, &default_decorate_req, ec);
|
host, target, &default_decorate_req, ec);
|
||||||
@@ -352,7 +352,7 @@ handshake_ex(string_view const& host,
|
|||||||
RequestDecorator const& decorator,
|
RequestDecorator const& decorator,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(detail::is_RequestDecorator<
|
static_assert(detail::is_RequestDecorator<
|
||||||
RequestDecorator>::value,
|
RequestDecorator>::value,
|
||||||
@@ -371,7 +371,7 @@ handshake_ex(response_type& res,
|
|||||||
RequestDecorator const& decorator,
|
RequestDecorator const& decorator,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(detail::is_RequestDecorator<
|
static_assert(detail::is_RequestDecorator<
|
||||||
RequestDecorator>::value,
|
RequestDecorator>::value,
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
#include <beast/core/bind_handler.hpp>
|
#include <beast/core/bind_handler.hpp>
|
||||||
#include <beast/core/handler_helpers.hpp>
|
#include <beast/core/handler_helpers.hpp>
|
||||||
#include <beast/core/handler_ptr.hpp>
|
#include <beast/core/handler_ptr.hpp>
|
||||||
#include <beast/core/stream_concepts.hpp>
|
#include <beast/core/type_traits.hpp>
|
||||||
#include <beast/websocket/detail/frame.hpp>
|
#include <beast/websocket/detail/frame.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@@ -200,7 +200,7 @@ async_return_type<
|
|||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
async_ping(ping_data const& payload, WriteHandler&& handler)
|
async_ping(ping_data const& payload, WriteHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
"AsyncStream requirements requirements not met");
|
"AsyncStream requirements requirements not met");
|
||||||
async_completion<WriteHandler,
|
async_completion<WriteHandler,
|
||||||
void(error_code)> init{handler};
|
void(error_code)> init{handler};
|
||||||
@@ -217,7 +217,7 @@ async_return_type<
|
|||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
async_pong(ping_data const& payload, WriteHandler&& handler)
|
async_pong(ping_data const& payload, WriteHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
"AsyncStream requirements requirements not met");
|
"AsyncStream requirements requirements not met");
|
||||||
async_completion<WriteHandler,
|
async_completion<WriteHandler,
|
||||||
void(error_code)> init{handler};
|
void(error_code)> init{handler};
|
||||||
|
@@ -9,12 +9,11 @@
|
|||||||
#define BEAST_WEBSOCKET_IMPL_READ_IPP
|
#define BEAST_WEBSOCKET_IMPL_READ_IPP
|
||||||
|
|
||||||
#include <beast/websocket/teardown.hpp>
|
#include <beast/websocket/teardown.hpp>
|
||||||
#include <beast/core/buffer_concepts.hpp>
|
|
||||||
#include <beast/core/handler_helpers.hpp>
|
#include <beast/core/handler_helpers.hpp>
|
||||||
#include <beast/core/handler_ptr.hpp>
|
#include <beast/core/handler_ptr.hpp>
|
||||||
#include <beast/core/prepare_buffer.hpp>
|
#include <beast/core/prepare_buffer.hpp>
|
||||||
#include <beast/core/static_buffer.hpp>
|
#include <beast/core/static_buffer.hpp>
|
||||||
#include <beast/core/stream_concepts.hpp>
|
#include <beast/core/type_traits.hpp>
|
||||||
#include <beast/core/detail/clamp.hpp>
|
#include <beast/core/detail/clamp.hpp>
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
@@ -692,7 +691,7 @@ stream<NextLayer>::
|
|||||||
async_read_frame(frame_info& fi,
|
async_read_frame(frame_info& fi,
|
||||||
DynamicBuffer& dynabuf, ReadHandler&& handler)
|
DynamicBuffer& dynabuf, ReadHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
"AsyncStream requirements requirements not met");
|
"AsyncStream requirements requirements not met");
|
||||||
static_assert(beast::is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(beast::is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
@@ -710,7 +709,7 @@ void
|
|||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
read_frame(frame_info& fi, DynamicBuffer& dynabuf)
|
read_frame(frame_info& fi, DynamicBuffer& dynabuf)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(beast::is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(beast::is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
@@ -726,7 +725,7 @@ void
|
|||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
read_frame(frame_info& fi, DynamicBuffer& dynabuf, error_code& ec)
|
read_frame(frame_info& fi, DynamicBuffer& dynabuf, error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(beast::is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(beast::is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
@@ -1104,7 +1103,7 @@ stream<NextLayer>::
|
|||||||
async_read(opcode& op,
|
async_read(opcode& op,
|
||||||
DynamicBuffer& dynabuf, ReadHandler&& handler)
|
DynamicBuffer& dynabuf, ReadHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
"AsyncStream requirements requirements not met");
|
"AsyncStream requirements requirements not met");
|
||||||
static_assert(beast::is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(beast::is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
@@ -1122,7 +1121,7 @@ void
|
|||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
read(opcode& op, DynamicBuffer& dynabuf)
|
read(opcode& op, DynamicBuffer& dynabuf)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(beast::is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(beast::is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
@@ -1138,7 +1137,7 @@ void
|
|||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
read(opcode& op, DynamicBuffer& dynabuf, error_code& ec)
|
read(opcode& op, DynamicBuffer& dynabuf, error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(beast::is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(beast::is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
|
@@ -10,8 +10,8 @@
|
|||||||
|
|
||||||
#include <beast/core/async_result.hpp>
|
#include <beast/core/async_result.hpp>
|
||||||
#include <beast/core/handler_helpers.hpp>
|
#include <beast/core/handler_helpers.hpp>
|
||||||
#include <beast/core/handler_concepts.hpp>
|
|
||||||
#include <beast/core/handler_ptr.hpp>
|
#include <beast/core/handler_ptr.hpp>
|
||||||
|
#include <beast/core/type_traits.hpp>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace websocket {
|
namespace websocket {
|
||||||
@@ -139,7 +139,7 @@ async_teardown(teardown_tag,
|
|||||||
boost::asio::ssl::stream<AsyncStream>& stream,
|
boost::asio::ssl::stream<AsyncStream>& stream,
|
||||||
TeardownHandler&& handler)
|
TeardownHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(beast::is_CompletionHandler<
|
static_assert(beast::is_completion_handler<
|
||||||
TeardownHandler, void(error_code)>::value,
|
TeardownHandler, void(error_code)>::value,
|
||||||
"TeardownHandler requirements not met");
|
"TeardownHandler requirements not met");
|
||||||
detail::teardown_ssl_op<AsyncStream, typename std::decay<
|
detail::teardown_ssl_op<AsyncStream, typename std::decay<
|
||||||
|
@@ -16,11 +16,10 @@
|
|||||||
#include <beast/http/write.hpp>
|
#include <beast/http/write.hpp>
|
||||||
#include <beast/http/rfc7230.hpp>
|
#include <beast/http/rfc7230.hpp>
|
||||||
#include <beast/core/buffer_cat.hpp>
|
#include <beast/core/buffer_cat.hpp>
|
||||||
#include <beast/core/buffer_concepts.hpp>
|
|
||||||
#include <beast/core/consuming_buffers.hpp>
|
#include <beast/core/consuming_buffers.hpp>
|
||||||
#include <beast/core/prepare_buffer.hpp>
|
#include <beast/core/prepare_buffer.hpp>
|
||||||
#include <beast/core/static_buffer.hpp>
|
#include <beast/core/static_buffer.hpp>
|
||||||
#include <beast/core/stream_concepts.hpp>
|
#include <beast/core/type_traits.hpp>
|
||||||
#include <beast/core/detail/type_traits.hpp>
|
#include <beast/core/detail/type_traits.hpp>
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/endian/buffers.hpp>
|
#include <boost/endian/buffers.hpp>
|
||||||
@@ -29,6 +28,8 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace websocket {
|
namespace websocket {
|
||||||
|
|
||||||
|
@@ -9,9 +9,9 @@
|
|||||||
#define BEAST_WEBSOCKET_IMPL_TEARDOWN_IPP
|
#define BEAST_WEBSOCKET_IMPL_TEARDOWN_IPP
|
||||||
|
|
||||||
#include <beast/core/async_result.hpp>
|
#include <beast/core/async_result.hpp>
|
||||||
#include <beast/core/handler_concepts.hpp>
|
|
||||||
#include <beast/core/handler_helpers.hpp>
|
#include <beast/core/handler_helpers.hpp>
|
||||||
#include <beast/core/handler_ptr.hpp>
|
#include <beast/core/handler_ptr.hpp>
|
||||||
|
#include <beast/core/type_traits.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
@@ -152,7 +152,7 @@ async_teardown(teardown_tag,
|
|||||||
boost::asio::ip::tcp::socket& socket,
|
boost::asio::ip::tcp::socket& socket,
|
||||||
TeardownHandler&& handler)
|
TeardownHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(beast::is_CompletionHandler<
|
static_assert(beast::is_completion_handler<
|
||||||
TeardownHandler, void(error_code)>::value,
|
TeardownHandler, void(error_code)>::value,
|
||||||
"TeardownHandler requirements not met");
|
"TeardownHandler requirements not met");
|
||||||
detail::teardown_tcp_op<typename std::decay<
|
detail::teardown_tcp_op<typename std::decay<
|
||||||
|
@@ -10,13 +10,12 @@
|
|||||||
|
|
||||||
#include <beast/core/bind_handler.hpp>
|
#include <beast/core/bind_handler.hpp>
|
||||||
#include <beast/core/buffer_cat.hpp>
|
#include <beast/core/buffer_cat.hpp>
|
||||||
#include <beast/core/buffer_concepts.hpp>
|
|
||||||
#include <beast/core/consuming_buffers.hpp>
|
#include <beast/core/consuming_buffers.hpp>
|
||||||
#include <beast/core/handler_helpers.hpp>
|
#include <beast/core/handler_helpers.hpp>
|
||||||
#include <beast/core/handler_ptr.hpp>
|
#include <beast/core/handler_ptr.hpp>
|
||||||
#include <beast/core/prepare_buffer.hpp>
|
#include <beast/core/prepare_buffer.hpp>
|
||||||
#include <beast/core/static_buffer.hpp>
|
#include <beast/core/static_buffer.hpp>
|
||||||
#include <beast/core/stream_concepts.hpp>
|
#include <beast/core/type_traits.hpp>
|
||||||
#include <beast/core/detail/clamp.hpp>
|
#include <beast/core/detail/clamp.hpp>
|
||||||
#include <beast/websocket/detail/frame.hpp>
|
#include <beast/websocket/detail/frame.hpp>
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
@@ -551,7 +550,7 @@ stream<NextLayer>::
|
|||||||
async_write_frame(bool fin,
|
async_write_frame(bool fin,
|
||||||
ConstBufferSequence const& bs, WriteHandler&& handler)
|
ConstBufferSequence const& bs, WriteHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
"AsyncStream requirements not met");
|
"AsyncStream requirements not met");
|
||||||
static_assert(beast::is_const_buffer_sequence<
|
static_assert(beast::is_const_buffer_sequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
@@ -570,7 +569,7 @@ void
|
|||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
write_frame(bool fin, ConstBufferSequence const& buffers)
|
write_frame(bool fin, ConstBufferSequence const& buffers)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(beast::is_const_buffer_sequence<
|
static_assert(beast::is_const_buffer_sequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
@@ -588,7 +587,7 @@ stream<NextLayer>::
|
|||||||
write_frame(bool fin,
|
write_frame(bool fin,
|
||||||
ConstBufferSequence const& buffers, error_code& ec)
|
ConstBufferSequence const& buffers, error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(beast::is_const_buffer_sequence<
|
static_assert(beast::is_const_buffer_sequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
@@ -900,7 +899,7 @@ async_return_type<
|
|||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
async_write(ConstBufferSequence const& bs, WriteHandler&& handler)
|
async_write(ConstBufferSequence const& bs, WriteHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
"AsyncStream requirements not met");
|
"AsyncStream requirements not met");
|
||||||
static_assert(beast::is_const_buffer_sequence<
|
static_assert(beast::is_const_buffer_sequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
@@ -919,7 +918,7 @@ void
|
|||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
write(ConstBufferSequence const& buffers)
|
write(ConstBufferSequence const& buffers)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(beast::is_const_buffer_sequence<
|
static_assert(beast::is_const_buffer_sequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
@@ -936,7 +935,7 @@ void
|
|||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
write(ConstBufferSequence const& buffers, error_code& ec)
|
write(ConstBufferSequence const& buffers, error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(beast::is_const_buffer_sequence<
|
static_assert(beast::is_const_buffer_sequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
|
@@ -30,6 +30,21 @@ namespace websocket {
|
|||||||
the request should be routed to an instance of
|
the request should be routed to an instance of
|
||||||
@ref websocket::stream.
|
@ref websocket::stream.
|
||||||
|
|
||||||
|
@par Example
|
||||||
|
@code
|
||||||
|
void handle_connection(boost::asio::ip::tcp::socket& sock)
|
||||||
|
{
|
||||||
|
beast::flat_buffer buffer;
|
||||||
|
beast::http::request<beast::http::string_body> req;
|
||||||
|
beast::http::read(sock, buffer, req);
|
||||||
|
if(beast::websocket::is_upgrade(req))
|
||||||
|
{
|
||||||
|
beast::websocket::stream<decltype(sock)> ws{std::move(sock)};
|
||||||
|
ws.accept(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@endcode
|
||||||
|
|
||||||
@param req The HTTP Request object to check.
|
@param req The HTTP Request object to check.
|
||||||
|
|
||||||
@return `true` if the request is a WebSocket Upgrade.
|
@return `true` if the request is a WebSocket Upgrade.
|
||||||
|
@@ -81,17 +81,17 @@ struct frame_info
|
|||||||
|
|
||||||
@tparam NextLayer The type representing the next layer, to which
|
@tparam NextLayer The type representing the next layer, to which
|
||||||
data will be read and written during operations. For synchronous
|
data will be read and written during operations. For synchronous
|
||||||
operations, the type must support the @b `SyncStream` concept.
|
operations, the type must support the @b SyncStream concept.
|
||||||
For asynchronous operations, the type must support the
|
For asynchronous operations, the type must support the
|
||||||
@b `AsyncStream` concept.
|
@b AsyncStream concept.
|
||||||
|
|
||||||
@note A stream object must not be moved or destroyed while there
|
@note A stream object must not be moved or destroyed while there
|
||||||
are pending asynchronous operations associated with it.
|
are pending asynchronous operations associated with it.
|
||||||
|
|
||||||
@par Concepts
|
@par Concepts
|
||||||
@b `AsyncStream`,
|
@b AsyncStream,
|
||||||
@b `DynamicBuffer`,
|
@b DynamicBuffer,
|
||||||
@b `SyncStream`
|
@b SyncStream
|
||||||
*/
|
*/
|
||||||
template<class NextLayer>
|
template<class NextLayer>
|
||||||
class stream : public detail::stream_base
|
class stream : public detail::stream_base
|
||||||
|
@@ -19,7 +19,6 @@ unit-test core-tests :
|
|||||||
core/async_result.cpp
|
core/async_result.cpp
|
||||||
core/bind_handler.cpp
|
core/bind_handler.cpp
|
||||||
core/buffer_cat.cpp
|
core/buffer_cat.cpp
|
||||||
core/buffer_concepts.cpp
|
|
||||||
core/buffered_read_stream.cpp
|
core/buffered_read_stream.cpp
|
||||||
core/buffers_adapter.cpp
|
core/buffers_adapter.cpp
|
||||||
core/clamp.cpp
|
core/clamp.cpp
|
||||||
@@ -27,19 +26,17 @@ unit-test core-tests :
|
|||||||
core/error.cpp
|
core/error.cpp
|
||||||
core/flat_buffer.cpp
|
core/flat_buffer.cpp
|
||||||
core/handler_alloc.cpp
|
core/handler_alloc.cpp
|
||||||
core/handler_concepts.cpp
|
|
||||||
core/handler_ptr.cpp
|
core/handler_ptr.cpp
|
||||||
core/multi_buffer.cpp
|
core/multi_buffer.cpp
|
||||||
core/ostream.cpp
|
core/ostream.cpp
|
||||||
core/prepare_buffer.cpp
|
core/prepare_buffer.cpp
|
||||||
core/static_buffer.cpp
|
core/static_buffer.cpp
|
||||||
core/static_string.cpp
|
core/static_string.cpp
|
||||||
core/stream_concepts.cpp
|
|
||||||
core/string_view.cpp
|
core/string_view.cpp
|
||||||
|
core/type_traits.cpp
|
||||||
core/base64.cpp
|
core/base64.cpp
|
||||||
core/empty_base_optimization.cpp
|
core/empty_base_optimization.cpp
|
||||||
core/sha1.cpp
|
core/sha1.cpp
|
||||||
core/type_traits.cpp
|
|
||||||
;
|
;
|
||||||
|
|
||||||
unit-test http-tests :
|
unit-test http-tests :
|
||||||
|
@@ -12,7 +12,6 @@ add_executable (core-tests
|
|||||||
async_result.cpp
|
async_result.cpp
|
||||||
bind_handler.cpp
|
bind_handler.cpp
|
||||||
buffer_cat.cpp
|
buffer_cat.cpp
|
||||||
buffer_concepts.cpp
|
|
||||||
buffers_adapter.cpp
|
buffers_adapter.cpp
|
||||||
clamp.cpp
|
clamp.cpp
|
||||||
consuming_buffers.cpp
|
consuming_buffers.cpp
|
||||||
@@ -20,23 +19,19 @@ add_executable (core-tests
|
|||||||
error.cpp
|
error.cpp
|
||||||
flat_buffer.cpp
|
flat_buffer.cpp
|
||||||
handler_alloc.cpp
|
handler_alloc.cpp
|
||||||
handler_concepts.cpp
|
|
||||||
handler_ptr.cpp
|
handler_ptr.cpp
|
||||||
multi_buffer.cpp
|
multi_buffer.cpp
|
||||||
ostream.cpp
|
ostream.cpp
|
||||||
prepare_buffer.cpp
|
prepare_buffer.cpp
|
||||||
static_buffer.cpp
|
static_buffer.cpp
|
||||||
static_string.cpp
|
static_string.cpp
|
||||||
stream_concepts.cpp
|
|
||||||
string_view.cpp
|
string_view.cpp
|
||||||
|
type_traits.cpp
|
||||||
base64.cpp
|
base64.cpp
|
||||||
empty_base_optimization.cpp
|
empty_base_optimization.cpp
|
||||||
sha1.cpp
|
sha1.cpp
|
||||||
type_traits.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if (NOT WIN32)
|
if (NOT WIN32)
|
||||||
target_link_libraries(core-tests ${Boost_LIBRARIES} Threads::Threads)
|
target_link_libraries(core-tests ${Boost_LIBRARIES} Threads::Threads)
|
||||||
else()
|
|
||||||
target_link_libraries(core-tests ${Boost_LIBRARIES})
|
|
||||||
endif()
|
endif()
|
||||||
|
@@ -1,25 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2013-2017 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)
|
|
||||||
//
|
|
||||||
|
|
||||||
// Test that header file is self-contained.
|
|
||||||
#include <beast/core/buffer_concepts.hpp>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
struct T
|
|
||||||
{
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static_assert(is_const_buffer_sequence<detail::ConstBufferSequence>::value, "");
|
|
||||||
static_assert(! is_const_buffer_sequence<T>::value, "");
|
|
||||||
|
|
||||||
static_assert(is_mutable_buffer_sequence<detail::MutableBufferSequence>::value, "");
|
|
||||||
static_assert(! is_mutable_buffer_sequence<T>::value, "");
|
|
||||||
|
|
||||||
} // beast
|
|
@@ -8,7 +8,7 @@
|
|||||||
#ifndef BEAST_TEST_BUFFER_TEST_HPP
|
#ifndef BEAST_TEST_BUFFER_TEST_HPP
|
||||||
#define BEAST_TEST_BUFFER_TEST_HPP
|
#define BEAST_TEST_BUFFER_TEST_HPP
|
||||||
|
|
||||||
#include <beast/core/buffer_concepts.hpp>
|
#include <beast/core/type_traits.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
@@ -1,23 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2013-2017 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)
|
|
||||||
//
|
|
||||||
|
|
||||||
// Test that header file is self-contained.
|
|
||||||
#include <beast/core/handler_concepts.hpp>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
struct T
|
|
||||||
{
|
|
||||||
void operator()(int);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static_assert(is_CompletionHandler<T, void(int)>::value, "");
|
|
||||||
static_assert(! is_CompletionHandler<T, void(void)>::value, "");
|
|
||||||
|
|
||||||
} // beast
|
|
@@ -9,8 +9,8 @@
|
|||||||
#include <beast/core/multi_buffer.hpp>
|
#include <beast/core/multi_buffer.hpp>
|
||||||
|
|
||||||
#include "buffer_test.hpp"
|
#include "buffer_test.hpp"
|
||||||
#include <beast/core/buffer_concepts.hpp>
|
|
||||||
#include <beast/core/ostream.hpp>
|
#include <beast/core/ostream.hpp>
|
||||||
|
#include <beast/core/type_traits.hpp>
|
||||||
#include <beast/test/test_allocator.hpp>
|
#include <beast/test/test_allocator.hpp>
|
||||||
#include <beast/unit_test/suite.hpp>
|
#include <beast/unit_test/suite.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
|
@@ -1,30 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2013-2017 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)
|
|
||||||
//
|
|
||||||
|
|
||||||
// Test that header file is self-contained.
|
|
||||||
#include <beast/core/stream_concepts.hpp>
|
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
using stream_type = boost::asio::ip::tcp::socket;
|
|
||||||
|
|
||||||
static_assert(has_get_io_service<stream_type>::value, "");
|
|
||||||
static_assert(is_AsyncReadStream<stream_type>::value, "");
|
|
||||||
static_assert(is_AsyncWriteStream<stream_type>::value, "");
|
|
||||||
static_assert(is_AsyncStream<stream_type>::value, "");
|
|
||||||
static_assert(is_SyncReadStream<stream_type>::value, "");
|
|
||||||
static_assert(is_SyncWriteStream<stream_type>::value, "");
|
|
||||||
static_assert(is_SyncStream<stream_type>::value, "");
|
|
||||||
|
|
||||||
static_assert(! has_get_io_service<int>::value, "");
|
|
||||||
static_assert(! is_AsyncReadStream<int>::value, "");
|
|
||||||
static_assert(! is_AsyncWriteStream<int>::value, "");
|
|
||||||
static_assert(! is_SyncReadStream<int>::value, "");
|
|
||||||
static_assert(! is_SyncWriteStream<int>::value, "");
|
|
||||||
|
|
||||||
} // beast
|
|
@@ -6,9 +6,12 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
// Test that header file is self-contained.
|
// Test that header file is self-contained.
|
||||||
#include <beast/core/detail/type_traits.hpp>
|
#include <beast/core/type_traits.hpp>
|
||||||
|
|
||||||
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -60,13 +63,8 @@ static_assert(! is_invocable<
|
|||||||
// get_lowest_layer
|
// get_lowest_layer
|
||||||
//
|
//
|
||||||
|
|
||||||
struct F1
|
struct F1 {};
|
||||||
{
|
struct F2 {};
|
||||||
};
|
|
||||||
|
|
||||||
struct F2
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class F>
|
template<class F>
|
||||||
struct F3
|
struct F3
|
||||||
@@ -120,4 +118,61 @@ static_assert(std::is_same<
|
|||||||
} // (anonymous)
|
} // (anonymous)
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
|
|
||||||
|
//
|
||||||
|
// buffer concepts
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct T {};
|
||||||
|
|
||||||
|
static_assert(is_const_buffer_sequence<detail::ConstBufferSequence>::value, "");
|
||||||
|
static_assert(! is_const_buffer_sequence<T>::value, "");
|
||||||
|
|
||||||
|
static_assert(is_mutable_buffer_sequence<detail::MutableBufferSequence>::value, "");
|
||||||
|
static_assert(! is_mutable_buffer_sequence<T>::value, "");
|
||||||
|
|
||||||
|
} // (anonymous)
|
||||||
|
|
||||||
|
//
|
||||||
|
// handler concepts
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct H
|
||||||
|
{
|
||||||
|
void operator()(int);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // anonymous
|
||||||
|
|
||||||
|
static_assert(is_completion_handler<H, void(int)>::value, "");
|
||||||
|
static_assert(! is_completion_handler<H, void(void)>::value, "");
|
||||||
|
|
||||||
|
//
|
||||||
|
// stream concepts
|
||||||
|
//
|
||||||
|
|
||||||
|
//namespace {
|
||||||
|
|
||||||
|
using stream_type = boost::asio::ip::tcp::socket;
|
||||||
|
|
||||||
|
static_assert(has_get_io_service<stream_type>::value, "");
|
||||||
|
static_assert(is_async_read_stream<stream_type>::value, "");
|
||||||
|
static_assert(is_async_write_stream<stream_type>::value, "");
|
||||||
|
static_assert(is_async_stream<stream_type>::value, "");
|
||||||
|
static_assert(is_sync_read_stream<stream_type>::value, "");
|
||||||
|
static_assert(is_sync_write_stream<stream_type>::value, "");
|
||||||
|
static_assert(is_sync_stream<stream_type>::value, "");
|
||||||
|
|
||||||
|
static_assert(! has_get_io_service<int>::value, "");
|
||||||
|
static_assert(! is_async_read_stream<int>::value, "");
|
||||||
|
static_assert(! is_async_write_stream<int>::value, "");
|
||||||
|
static_assert(! is_sync_read_stream<int>::value, "");
|
||||||
|
static_assert(! is_sync_write_stream<int>::value, "");
|
||||||
|
|
||||||
|
//} // (anonymous)
|
||||||
|
|
||||||
} // beast
|
} // beast
|
||||||
|
@@ -12,8 +12,8 @@
|
|||||||
|
|
||||||
#include <beast/http/message.hpp>
|
#include <beast/http/message.hpp>
|
||||||
#include <beast/http/rfc7230.hpp>
|
#include <beast/http/rfc7230.hpp>
|
||||||
#include <beast/core/buffer_concepts.hpp>
|
|
||||||
#include <beast/core/error.hpp>
|
#include <beast/core/error.hpp>
|
||||||
|
#include <beast/core/type_traits.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <boost/system/error_code.hpp>
|
#include <boost/system/error_code.hpp>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
Reference in New Issue
Block a user