mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 04:47:29 +02:00
Update for Net-TS Asio (API Change):
fix #769 The following classes are removed: * handler_type * async_result * async_completion * is_dynamic_buffer * is_const_buffer_sequence * is_mutable_buffer_sequence * handler_alloc Actions Required: * Use BOOST_ASIO_HANDLER_TYPE instead of handler_type * Use BOOST_ASIO_INITFN_RESULT_TYPE instead of async_result * Use boost::asio::async_completion * Use boost::asio::is_dynamic_buffer * Use boost::asio::is_const_buffer_sequence * Use boost::asio::is_mutable_buffer_sequence * boost::asio::associated_allocator_t replaces handler_alloc
This commit is contained in:
18
CHANGELOG.md
18
CHANGELOG.md
@ -1,3 +1,21 @@
|
||||
Version 125:
|
||||
|
||||
API Changes:
|
||||
|
||||
* Update for Net-TS Asio
|
||||
|
||||
Actions Required:
|
||||
|
||||
* Use BOOST_ASIO_HANDLER_TYPE instead of handler_type
|
||||
* Use BOOST_ASIO_INITFN_RESULT_TYPE instead of async_result
|
||||
* Use boost::asio::async_completion
|
||||
* Use boost::asio::is_dynamic_buffer
|
||||
* Use boost::asio::is_const_buffer_sequence
|
||||
* Use boost::asio::is_mutable_buffer_sequence
|
||||
* boost::asio::associated_allocator_t replaces handler_alloc
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Version 124:
|
||||
|
||||
* Fix for a test matrix compiler
|
||||
|
@ -21,7 +21,6 @@ if (MSVC)
|
||||
add_definitions (-D_WIN32_WINNT=0x0601)
|
||||
add_definitions (-D_SCL_SECURE_NO_WARNINGS=1)
|
||||
add_definitions (-D_CRT_SECURE_NO_WARNINGS=1)
|
||||
add_definitions (-DBOOST_ASIO_NO_DEPRECATED=1)
|
||||
|
||||
add_compile_options(
|
||||
/bigobj # large object file format
|
||||
@ -75,6 +74,7 @@ get_filename_component (BOOST_ROOT ../../ ABSOLUTE)
|
||||
# VFALCO I want static but "b2 stage" builds a minimal set which excludes static
|
||||
add_definitions (-DBOOST_ALL_STATIC_LINK=1)
|
||||
|
||||
add_definitions (-DBOOST_ASIO_NO_DEPRECATED=1)
|
||||
add_definitions (-DBOOST_ASIO_DISABLE_BOOST_ARRAY=1)
|
||||
add_definitions (-DBOOST_ASIO_DISABLE_BOOST_BIND=1)
|
||||
add_definitions (-DBOOST_ASIO_DISABLE_BOOST_DATE_TIME=1)
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |
@ -38,7 +38,7 @@
|
||||
|
||||
[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/html/boost_asio/reference/asio_handler_allocate.html `asio_handler_allocate`]]
|
||||
[def __io_service__ [@http://www.boost.org/doc/html/boost_asio/reference/io_service.html `io_service`]]
|
||||
[def __io_context__ [@http://www.boost.org/doc/html/boost_asio/reference/io_context.html `io_context`]]
|
||||
[def __socket__ [@http://www.boost.org/doc/html/boost_asio/reference/ip__tcp/socket.html `boost::asio::ip::tcp::socket`]]
|
||||
[def __ssl_stream__ [@http://www.boost.org/doc/html/boost_asio/reference/ssl__stream.html `boost::asio::ssl::stream`]]
|
||||
[def __streambuf__ [@http://www.boost.org/doc/html/boost_asio/reference/streambuf.html `boost::asio::streambuf`]]
|
||||
|
@ -30,12 +30,12 @@ special meaning:
|
||||
[table Global Variables
|
||||
[[Name][Description]]
|
||||
[[
|
||||
[@http://www.boost.org/doc/html/boost_asio/reference/io_service.html [*`ios`]]
|
||||
[@http://www.boost.org/doc/html/boost_asio/reference/io_context.html [*`ioc`]]
|
||||
][
|
||||
A variable of type
|
||||
[@http://www.boost.org/doc/html/boost_asio/reference/io_service.html `boost::asio::io_service`]
|
||||
which is running on one separate thread, and upon which a
|
||||
[@http://www.boost.org/doc/html/boost_asio/reference/io_service__work.html `boost::asio::io_service::work`]
|
||||
[@http://www.boost.org/doc/html/boost_asio/reference/io_context.html `boost::asio::io_context`]
|
||||
which is running on one separate thread, and upon which an
|
||||
[@http://www.boost.org/doc/html/boost_asio/reference/executor_work.html `boost::asio::executor_work`]
|
||||
object has been constructed.
|
||||
]]
|
||||
[[
|
||||
|
@ -67,10 +67,9 @@ checks helps provide more concise errors during compilation:
|
||||
Returns `T::lowest_layer_type` if it exists, else returns `T`.
|
||||
]]
|
||||
[[
|
||||
[link beast.ref.boost__beast__has_get_io_service `has_get_io_service`]
|
||||
[link beast.ref.boost__beast__has_get_executor `has_get_executor`]
|
||||
][
|
||||
Determine if the `get_io_service` member function is present,
|
||||
and returns an __io_service__.
|
||||
Determine if the `get_executor` member function is present.
|
||||
]]
|
||||
[[
|
||||
[link beast.ref.boost__beast__is_async_read_stream `is_async_read_stream`]
|
||||
|
@ -9,36 +9,71 @@
|
||||
|
||||
[section Buffer Types]
|
||||
|
||||
__Asio__ provides the __ConstBufferSequence__ and __MutableBufferSequence__
|
||||
concepts, whose models provide ranges of buffers, as well as the __streambuf__
|
||||
class which encapsulates memory storage that may be automatically resized as
|
||||
required, where the memory is divided into an input sequence followed by an
|
||||
output sequence. The Networking TS (__N4588__) generalizes this `streambuf`
|
||||
interface into the __DynamicBuffer__ concept. Beast algorithms which require
|
||||
resizable buffers accept dynamic buffer objects as templated parameters.
|
||||
These metafunctions check if types match the buffer concepts:
|
||||
To facilitate working with instances of the __ConstBufferSequence__ and
|
||||
__MutableBufferSequence__ concepts introduced in __Asio__, Beast treats
|
||||
those sequences as a special type of range. The following algorithms and
|
||||
wrappers are provided which transform these ranges efficiently using lazy
|
||||
evaluation. No memory allocations are used in the transformations; instead,
|
||||
they create lightweight iterators over the existing, unmodified memory
|
||||
buffers. Control of buffers is retained by the caller; ownership is not
|
||||
transferred.
|
||||
|
||||
[table Buffer Type Checks
|
||||
[table Buffer Algorithms and Types
|
||||
[[Name][Description]]
|
||||
[[
|
||||
[link beast.ref.boost__beast__is_dynamic_buffer `is_dynamic_buffer`]
|
||||
[link beast.ref.boost__beast__buffers_cat `buffers_cat`]
|
||||
][
|
||||
Determine if a type meets the requirements of __DynamicBuffer__.
|
||||
This 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. With this routine, multiple calls to a
|
||||
stream's `write_some` function may be combined into one, eliminating
|
||||
expensive system calls.
|
||||
]]
|
||||
[[
|
||||
[link beast.ref.boost__beast__is_const_buffer_sequence `is_const_buffer_sequence`]
|
||||
[link beast.ref.boost__beast__buffers_cat_view `buffers_cat_view`]
|
||||
][
|
||||
Determine if a type meets the requirements of __ConstBufferSequence__.
|
||||
This class represents the buffer sequence formed by concatenating
|
||||
two or more buffer sequences. This is type of object returned by
|
||||
[link beast.ref.boost__beast__buffers_cat `buffers_cat`].
|
||||
]]
|
||||
[[
|
||||
[link beast.ref.boost__beast__is_mutable_buffer_sequence `is_mutable_buffer_sequence`]
|
||||
[link beast.ref.boost__beast__buffers_front `buffers_front`]
|
||||
][
|
||||
Determine if a type meets the requirements of __MutableBufferSequence__.
|
||||
This function returns the first buffer in a buffer sequence,
|
||||
or a buffer of size zero if the buffer sequence has no elements.
|
||||
]]
|
||||
[[
|
||||
[link beast.ref.boost__beast__buffers_prefix `buffers_prefix`]
|
||||
][
|
||||
This function returns a new buffer or buffer sequence which represents
|
||||
a prefix of the original buffers.
|
||||
]]
|
||||
[[
|
||||
[link beast.ref.boost__beast__buffers_prefix_view `buffers_prefix_view`]
|
||||
][
|
||||
This class represents the buffer sequence formed from a prefix of
|
||||
an existing buffer sequence. This is the type of buffer returned by
|
||||
[link beast.ref.boost__beast__buffers_prefix.overload3 `buffers_prefix`].
|
||||
]]
|
||||
[[
|
||||
[link beast.ref.boost__beast__buffers_suffix `buffers_suffix`]
|
||||
][
|
||||
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.boost__beast__buffers_to_string `buffers_to_string`]
|
||||
][
|
||||
This function converts a buffer sequence to a `std::string`. It can
|
||||
be used for diagnostic purposes and tests.
|
||||
]]
|
||||
]
|
||||
|
||||
Beast provides several dynamic buffer implementations for a variety
|
||||
of scenarios:
|
||||
The __DynamicBuffer__ concept introduced in __Asio__ models a buffer
|
||||
sequence which supports an owning, resizable range. Beast provides this
|
||||
set of additional implementations of the dynamic buffer concept:
|
||||
|
||||
[table Dynamic Buffer Implementations
|
||||
[[Name][Description]]
|
||||
@ -95,68 +130,6 @@ of scenarios:
|
||||
]]
|
||||
]
|
||||
|
||||
Network applications frequently need to manipulate buffer sequences. To
|
||||
facilitate working with buffers the library treats these sequences as
|
||||
a special type of range. Algorithms and wrappers are provided which
|
||||
transform these ranges efficiently using lazy evaluation. No memory
|
||||
allocations are used in the transformations; instead, they create
|
||||
lightweight iterators over the existing, unmodified memory buffers.
|
||||
Control of buffers is retained by the caller; ownership is not
|
||||
transferred.
|
||||
|
||||
[table Buffer Algorithms and Types
|
||||
[[Name][Description]]
|
||||
[[
|
||||
[link beast.ref.boost__beast__buffers_cat `buffers_cat`]
|
||||
][
|
||||
This 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. With this routine, multiple calls to a
|
||||
stream's `write_some` function may be combined into one, eliminating
|
||||
expensive system calls.
|
||||
]]
|
||||
[[
|
||||
[link beast.ref.boost__beast__buffers_cat_view `buffers_cat_view`]
|
||||
][
|
||||
This class represents the buffer sequence formed by concatenating
|
||||
two or more buffer sequences. This is type of object returned by
|
||||
[link beast.ref.boost__beast__buffers_cat `buffers_cat`].
|
||||
]]
|
||||
[[
|
||||
[link beast.ref.boost__beast__buffers_front `buffers_front`]
|
||||
][
|
||||
This function returns the first buffer in a buffer sequence,
|
||||
or a buffer of size zero if the buffer sequence has no elements.
|
||||
]]
|
||||
[[
|
||||
[link beast.ref.boost__beast__buffers_prefix `buffers_prefix`]
|
||||
][
|
||||
This function returns a new buffer or buffer sequence which represents
|
||||
a prefix of the original buffers.
|
||||
]]
|
||||
[[
|
||||
[link beast.ref.boost__beast__buffers_prefix_view `buffers_prefix_view`]
|
||||
][
|
||||
This class represents the buffer sequence formed from a prefix of
|
||||
an existing buffer sequence. This is the type of buffer returned by
|
||||
[link beast.ref.boost__beast__buffers_prefix.overload3 `buffers_prefix`].
|
||||
]]
|
||||
[[
|
||||
[link beast.ref.boost__beast__buffers_suffix `buffers_suffix`]
|
||||
][
|
||||
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.boost__beast__buffers_to_string `buffers_to_string`]
|
||||
][
|
||||
This function converts a buffer sequence to a `std::string`. It can
|
||||
be used for diagnostic purposes and tests.
|
||||
]]
|
||||
]
|
||||
|
||||
These two functions facilitate buffer interoperability with standard
|
||||
output streams.
|
||||
|
||||
|
@ -38,23 +38,6 @@ composed operations:
|
||||
|
||||
[table Asynchronous Helpers
|
||||
[[Name][Description]]
|
||||
[[
|
||||
[link beast.ref.boost__beast__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.boost__beast__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.boost__beast__bind_handler `bind_handler`]
|
||||
][
|
||||
@ -66,15 +49,6 @@ composed operations:
|
||||
`asio_handler_invoke` associated with the original completion handler.
|
||||
|
||||
]]
|
||||
[[
|
||||
[link beast.ref.boost__beast__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.boost__beast__handler_ptr `handler_ptr`]
|
||||
][
|
||||
@ -87,14 +61,6 @@ composed operations:
|
||||
associated allocator, benefiting from all handler memory management
|
||||
optimizations transparently.
|
||||
]]
|
||||
[[
|
||||
[link beast.ref.boost__beast__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.
|
||||
]]
|
||||
]
|
||||
|
||||
|
||||
@ -203,27 +169,28 @@ composed operations:
|
||||
|
||||
* Type erasing the final handler. This will cause undefined behavior.
|
||||
|
||||
* Not using `std::addressof` to get the address of the handler.
|
||||
|
||||
* Forgetting to include a return statement after calling an
|
||||
initiating function.
|
||||
|
||||
* Calling a synchronous function by accident. In general composed
|
||||
operations should not block for long periods of time, since this
|
||||
ties up a thread running on the __io_service__.
|
||||
ties up a thread running on the __io_context__.
|
||||
|
||||
* Forgetting to overload `asio_handler_invoke` for the composed
|
||||
operation. This will cause undefined behavior if someone calls
|
||||
the initiating function with a strand-wrapped function object,
|
||||
and there is more than thread running on the `io_service`.
|
||||
* Forgetting to provide `executor_type` and `get_executor` for the
|
||||
composed operation. This will cause undefined behavior. For example,
|
||||
if someone calls the initiating function with a strand-wrapped
|
||||
function object, and there is more than thread running on the
|
||||
`io_context`, the underlying stream may be accessed in a fashion
|
||||
that violates safety guarantees.
|
||||
|
||||
* For operations which complete immediately (i.e. without calling an
|
||||
intermediate initiating function), forgetting to use `io_service::post`
|
||||
intermediate initiating function), forgetting to use
|
||||
[@http://www.boost.org/doc/html/boost_asio/reference/post.html `boost::asio::post`]
|
||||
to invoke the final handler. This breaks the following initiating
|
||||
function guarantee: ['Regardless of whether the asynchronous operation
|
||||
completes immediately or not, the handler will not be invoked from
|
||||
within this function. Invocation of the handler will be performed
|
||||
in a manner equivalent to using `boost::asio::io_service::post`].
|
||||
in a manner equivalent to using `boost::asio::post`].
|
||||
The function
|
||||
[link beast.ref.boost__beast__bind_handler `bind_handler`]
|
||||
is provided for this purpose.
|
||||
|
@ -83,9 +83,9 @@ as this example shows.
|
||||
If a read stream algorithm cannot complete its operation without exceeding
|
||||
the maximum specified size of the dynamic buffer provided, the error
|
||||
[link beast.ref.boost__beast__http__error `buffer_overflow`]
|
||||
is returned. This may be used to impose a limit on the maximum size of an
|
||||
HTTP message header for protection from buffer overflow attacks. The
|
||||
following code will print the error message:
|
||||
is returned. This is one technique which may be used to impose a limit on
|
||||
the maximum size of an HTTP message header for protection from buffer
|
||||
overflow attacks. The following code will print the error message:
|
||||
|
||||
[http_snippet_6]
|
||||
|
||||
|
@ -31,7 +31,7 @@ field value.
|
||||
|
||||
[heading Serializing Chunks]
|
||||
|
||||
The __serializer__ automatically applies the chunked tranfer encoding
|
||||
The __serializer__ automatically applies the chunked transfer encoding
|
||||
when a message returns `true` from
|
||||
[link beast.ref.boost__beast__http__message.chunked.overload1 `message::chunked`].
|
||||
The boundaries between chunks emitted by the serializer are implementation
|
||||
|
@ -19,7 +19,7 @@ are performed, or both. Any arguments supplied during construction of
|
||||
the stream wrapper are passed to next layer's constructor.
|
||||
|
||||
Here we declare a websocket stream over a TCP/IP socket with ownership
|
||||
of the socket. The `io_service` argument is forwarded to the wrapped
|
||||
of the socket. The `io_context` argument is forwarded to the wrapped
|
||||
socket's constructor:
|
||||
|
||||
[ws_snippet_2]
|
||||
@ -27,7 +27,7 @@ socket's constructor:
|
||||
[heading Using SSL]
|
||||
|
||||
To use WebSockets over SSL, use an instance of the `boost::asio::ssl::stream`
|
||||
class template as the template type for the stream. The required `io_service`
|
||||
class template as the template type for the stream. The required `io_context`
|
||||
and `ssl::context` arguments are forwarded to the wrapped stream's constructor:
|
||||
|
||||
[wss_snippet_1]
|
||||
|
@ -88,7 +88,7 @@ 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
|
||||
received HTTP message in an output reference argument of type
|
||||
[link beast.ref.boost__beast__websocket__response_type `response_type`]
|
||||
as follows:
|
||||
|
||||
|
@ -31,9 +31,12 @@ handlers, stackful or stackless coroutines, and even futures:
|
||||
|
||||
[ws_snippet_21]
|
||||
|
||||
[heading The io_service]
|
||||
The example programs that come with the library demonstrate the usage of
|
||||
websocket stream operations with all asynchronous varieties.
|
||||
|
||||
The creation and operation of the __io_service__ associated with the
|
||||
[heading The io_context]
|
||||
|
||||
The creation and operation of the __io_context__ associated with the
|
||||
underlying stream is left to the callers, permitting any implementation
|
||||
strategy including one that does not require threads for environments
|
||||
where threads are unavailable. Beast WebSocket itself does not use
|
||||
@ -45,8 +48,8 @@ Like a regular __Asio__ socket, a
|
||||
[link beast.ref.boost__beast__websocket__stream `stream`]
|
||||
is not thread safe. Callers are responsible for synchronizing operations on
|
||||
the socket using an implicit or explicit strand, as per the Asio documentation.
|
||||
The asynchronous interface supports one of each of the following operations
|
||||
to be active at the same time:
|
||||
The websocket stream asynchronous interface supports one of each of the
|
||||
following operations to be active at the same time:
|
||||
|
||||
* [link beast.ref.boost__beast__websocket__stream.async_read `async_read`] or [link beast.ref.boost__beast__websocket__stream.async_read_some `async_read_some`]
|
||||
* [link beast.ref.boost__beast__websocket__stream.async_write `async_write`] or [link beast.ref.boost__beast__websocket__stream.async_write_some `async_write_some`]
|
||||
|
@ -35,7 +35,7 @@ implementation strategies:
|
||||
|
||||
[heading Associated Types]
|
||||
|
||||
* [link beast.ref.boost__beast__is_dynamic_buffer `is_dynamic_buffer`]
|
||||
* `boost::asio::is_dynamic_buffer`
|
||||
* __ConstBufferSequence__
|
||||
* __MutableBufferSequence__
|
||||
|
||||
|
@ -190,7 +190,7 @@ In this table:
|
||||
[
|
||||
If `(v < 11 && b)`, then all "close" tokens present in the
|
||||
value are removed, and the "keep-alive" token is added to
|
||||
the valueif it is not already present.
|
||||
the value if it is not already present.
|
||||
][
|
||||
If `(v < 11 && ! b)`, then all "close" and "keep-alive"
|
||||
tokens present in the value are removed.
|
||||
|
@ -32,7 +32,7 @@ __MutableBufferSequence__ concepts for passing buffers to functions.
|
||||
The authors have found the dynamic buffer and buffer sequence interfaces to
|
||||
be optimal for interacting with Asio, and for other tasks such as incremental
|
||||
parsing of data in buffers (for example, parsing websocket frames stored
|
||||
in a [link beast.ref.boost__beast__flat_static_buffer `flat_static_buffer`]).
|
||||
in a [link beast.ref.boost__beast__static_buffer `static_buffer`]).
|
||||
|
||||
During the development of Beast the authors have studied other software
|
||||
packages and in particular the comments left during the Boost Review process
|
||||
|
@ -260,10 +260,10 @@ struct header<false, Fields> : Fields
|
||||
};
|
||||
```
|
||||
|
||||
The start-line data members are replaced traditional accessors using
|
||||
non-owning references to string buffers. The method is stored using
|
||||
a simple integer instead of the entire string, for the case where
|
||||
the method is recognized from the set of known verb strings.
|
||||
The start-line data members are replaced by traditional accessors
|
||||
using non-owning references to string buffers. The method is stored
|
||||
using a simple integer instead of the entire string, for the case
|
||||
where the method is recognized from the set of known verb strings.
|
||||
|
||||
Now we add a requirement to the fields type: management of the
|
||||
corresponding string is delegated to the [*Fields] container, which can
|
||||
|
@ -122,7 +122,7 @@ through the __asio_handler_invoke__ mechanism.
|
||||
|
||||
The only requirement in Beast is that calls to asynchronous initiation
|
||||
functions are made from the same implicit or explicit strand. For
|
||||
example, if the `io_service` associated with a `beast::websocket::stream`
|
||||
example, if the `io_context` associated with a `beast::websocket::stream`
|
||||
is single threaded, this counts as an implicit strand and no performance
|
||||
costs associated with mutexes are incurred.
|
||||
|
||||
|
@ -174,9 +174,6 @@
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Classes</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member><link linkend="beast.ref.boost__beast__async_completion">async_completion</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__async_result">async_result</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__async_return_type">async_return_type</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__basic_flat_buffer">basic_flat_buffer</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__basic_multi_buffer">basic_multi_buffer</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__buffered_read_stream">buffered_read_stream</link></member>
|
||||
@ -197,9 +194,7 @@
|
||||
<member><link linkend="beast.ref.boost__beast__flat_buffer">flat_buffer</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__flat_static_buffer">flat_static_buffer</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__flat_static_buffer_base">flat_static_buffer_base</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__handler_alloc">handler_alloc</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__handler_ptr">handler_ptr</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__handler_type">handler_type</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__iequal">iequal</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__iless">iless</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__multi_buffer">multi_buffer</link></member>
|
||||
@ -236,15 +231,12 @@
|
||||
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member><link linkend="beast.ref.boost__beast__get_lowest_layer">get_lowest_layer</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__has_get_io_service">has_get_io_service</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__has_get_executor">has_get_executor</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__is_async_read_stream">is_async_read_stream</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__is_async_write_stream">is_async_write_stream</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__is_async_stream">is_async_stream</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__is_completion_handler">is_completion_handler</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__is_const_buffer_sequence">is_const_buffer_sequence</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__is_dynamic_buffer">is_dynamic_buffer</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__is_file">is_file</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__is_mutable_buffer_sequence">is_mutable_buffer_sequence</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__is_sync_read_stream">is_sync_read_stream</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__is_sync_stream">is_sync_stream</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__is_sync_write_stream">is_sync_write_stream</link></member>
|
||||
|
@ -285,7 +285,9 @@ INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED = \
|
||||
BOOST_BEAST_DOXYGEN \
|
||||
BOOST_BEAST_USE_POSIX_FILE=1 \
|
||||
BOOST_BEAST_USE_WIN32_FILE=1
|
||||
BOOST_BEAST_USE_WIN32_FILE=1 \
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(t,a)=void_or_deduced \
|
||||
GENERATING_DOCUMENTATION
|
||||
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <boost/beast/http.hpp>
|
||||
#include <boost/beast/websocket.hpp>
|
||||
#include <boost/beast/version.hpp>
|
||||
#include <boost/asio/bind_executor.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/ssl/stream.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
@ -235,15 +236,16 @@ class websocket_session
|
||||
boost::beast::multi_buffer buffer_;
|
||||
|
||||
protected:
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::strand<
|
||||
boost::asio::io_context::executor_type> strand_;
|
||||
boost::asio::steady_timer timer_;
|
||||
|
||||
public:
|
||||
// Construct the session
|
||||
explicit
|
||||
websocket_session(boost::asio::io_service& ios)
|
||||
: strand_(ios)
|
||||
, timer_(ios,
|
||||
websocket_session(boost::asio::io_context& ioc)
|
||||
: strand_(ioc.get_executor())
|
||||
, timer_(ioc,
|
||||
(std::chrono::steady_clock::time_point::max)())
|
||||
{
|
||||
}
|
||||
@ -254,15 +256,17 @@ public:
|
||||
do_accept(http::request<Body, http::basic_fields<Allocator>> req)
|
||||
{
|
||||
// Set the timer
|
||||
timer_.expires_from_now(std::chrono::seconds(15));
|
||||
timer_.expires_after(std::chrono::seconds(15));
|
||||
|
||||
// Accept the websocket handshake
|
||||
derived().ws().async_accept(
|
||||
req,
|
||||
strand_.wrap(std::bind(
|
||||
&websocket_session::on_accept,
|
||||
derived().shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&websocket_session::on_accept,
|
||||
derived().shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
}
|
||||
|
||||
// Called when the timer expires.
|
||||
@ -273,15 +277,17 @@ public:
|
||||
return fail(ec, "timer");
|
||||
|
||||
// Verify that the timer really expired since the deadline may have moved.
|
||||
if(timer_.expires_at() <= std::chrono::steady_clock::now())
|
||||
if(timer_.expiry() <= std::chrono::steady_clock::now())
|
||||
derived().do_timeout();
|
||||
|
||||
// Wait on the timer
|
||||
timer_.async_wait(
|
||||
strand_.wrap(std::bind(
|
||||
&websocket_session::on_timer,
|
||||
derived().shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&websocket_session::on_timer,
|
||||
derived().shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -302,16 +308,18 @@ public:
|
||||
do_read()
|
||||
{
|
||||
// Set the timer
|
||||
timer_.expires_from_now(std::chrono::seconds(15));
|
||||
timer_.expires_after(std::chrono::seconds(15));
|
||||
|
||||
// Read a message into our buffer
|
||||
derived().ws().async_read(
|
||||
buffer_,
|
||||
strand_.wrap(std::bind(
|
||||
&websocket_session::on_read,
|
||||
derived().shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&websocket_session::on_read,
|
||||
derived().shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -336,11 +344,13 @@ public:
|
||||
derived().ws().text(derived().ws().got_text());
|
||||
derived().ws().async_write(
|
||||
buffer_.data(),
|
||||
strand_.wrap(std::bind(
|
||||
&websocket_session::on_write,
|
||||
derived().shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&websocket_session::on_write,
|
||||
derived().shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -378,7 +388,7 @@ public:
|
||||
explicit
|
||||
plain_websocket_session(tcp::socket socket)
|
||||
: websocket_session<plain_websocket_session>(
|
||||
socket.get_io_service())
|
||||
socket.get_executor().context())
|
||||
, ws_(std::move(socket))
|
||||
{
|
||||
}
|
||||
@ -412,15 +422,17 @@ public:
|
||||
close_ = true;
|
||||
|
||||
// Set the timer
|
||||
timer_.expires_from_now(std::chrono::seconds(15));
|
||||
timer_.expires_after(std::chrono::seconds(15));
|
||||
|
||||
// Close the WebSocket Connection
|
||||
ws_.async_close(
|
||||
websocket::close_code::normal,
|
||||
strand_.wrap(std::bind(
|
||||
&plain_websocket_session::on_close,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&plain_websocket_session::on_close,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -443,7 +455,8 @@ class ssl_websocket_session
|
||||
, public std::enable_shared_from_this<ssl_websocket_session>
|
||||
{
|
||||
websocket::stream<ssl_stream<tcp::socket>> ws_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::strand<
|
||||
boost::asio::io_context::executor_type> strand_;
|
||||
bool eof_ = false;
|
||||
|
||||
public:
|
||||
@ -451,9 +464,9 @@ public:
|
||||
explicit
|
||||
ssl_websocket_session(ssl_stream<tcp::socket> stream)
|
||||
: websocket_session<ssl_websocket_session>(
|
||||
stream.get_io_service())
|
||||
stream.get_executor().context())
|
||||
, ws_(std::move(stream))
|
||||
, strand_(ws_.get_io_service())
|
||||
, strand_(ws_.get_executor())
|
||||
{
|
||||
}
|
||||
|
||||
@ -483,14 +496,16 @@ public:
|
||||
eof_ = true;
|
||||
|
||||
// Set the timer
|
||||
timer_.expires_from_now(std::chrono::seconds(15));
|
||||
timer_.expires_after(std::chrono::seconds(15));
|
||||
|
||||
// Perform the SSL shutdown
|
||||
ws_.next_layer().async_shutdown(
|
||||
strand_.wrap(std::bind(
|
||||
&ssl_websocket_session::on_shutdown,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&ssl_websocket_session::on_shutdown,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -630,10 +645,12 @@ class http_session
|
||||
http::async_write(
|
||||
self_.derived().stream(),
|
||||
msg_,
|
||||
self_.strand_.wrap(std::bind(
|
||||
&http_session::on_write,
|
||||
self_.derived().shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
boost::asio::bind_executor(
|
||||
self_.strand_,
|
||||
std::bind(
|
||||
&http_session::on_write,
|
||||
self_.derived().shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
}
|
||||
};
|
||||
|
||||
@ -652,20 +669,21 @@ class http_session
|
||||
|
||||
protected:
|
||||
boost::asio::steady_timer timer_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::strand<
|
||||
boost::asio::io_context::executor_type> strand_;
|
||||
boost::beast::flat_buffer buffer_;
|
||||
|
||||
public:
|
||||
// Construct the session
|
||||
http_session(
|
||||
boost::asio::io_service& ios,
|
||||
boost::asio::io_context& ioc,
|
||||
boost::beast::flat_buffer buffer,
|
||||
std::string const& doc_root)
|
||||
: doc_root_(doc_root)
|
||||
, queue_(*this)
|
||||
, timer_(ios,
|
||||
, timer_(ioc,
|
||||
(std::chrono::steady_clock::time_point::max)())
|
||||
, strand_(ios)
|
||||
, strand_(ioc.get_executor())
|
||||
, buffer_(std::move(buffer))
|
||||
{
|
||||
}
|
||||
@ -674,17 +692,19 @@ public:
|
||||
do_read()
|
||||
{
|
||||
// Set the timer
|
||||
timer_.expires_from_now(std::chrono::seconds(15));
|
||||
timer_.expires_after(std::chrono::seconds(15));
|
||||
|
||||
// Read a request
|
||||
http::async_read(
|
||||
derived().stream(),
|
||||
buffer_,
|
||||
req_,
|
||||
strand_.wrap(std::bind(
|
||||
&http_session::on_read,
|
||||
derived().shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&http_session::on_read,
|
||||
derived().shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
}
|
||||
|
||||
// Called when the timer expires.
|
||||
@ -695,15 +715,17 @@ public:
|
||||
return fail(ec, "timer");
|
||||
|
||||
// Verify that the timer really expired since the deadline may have moved.
|
||||
if(timer_.expires_at() <= std::chrono::steady_clock::now())
|
||||
if(timer_.expiry() <= std::chrono::steady_clock::now())
|
||||
return derived().do_timeout();
|
||||
|
||||
// Wait on the timer
|
||||
timer_.async_wait(
|
||||
strand_.wrap(std::bind(
|
||||
&http_session::on_timer,
|
||||
derived().shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&http_session::on_timer,
|
||||
derived().shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -769,7 +791,8 @@ class plain_http_session
|
||||
, public std::enable_shared_from_this<plain_http_session>
|
||||
{
|
||||
tcp::socket socket_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::strand<
|
||||
boost::asio::io_context::executor_type> strand_;
|
||||
|
||||
public:
|
||||
// Create the http_session
|
||||
@ -778,11 +801,11 @@ public:
|
||||
boost::beast::flat_buffer buffer,
|
||||
std::string const& doc_root)
|
||||
: http_session<plain_http_session>(
|
||||
socket.get_io_service(),
|
||||
socket.get_executor().context(),
|
||||
std::move(buffer),
|
||||
doc_root)
|
||||
, socket_(std::move(socket))
|
||||
, strand_(socket_.get_io_service())
|
||||
, strand_(socket_.get_executor())
|
||||
{
|
||||
}
|
||||
|
||||
@ -838,7 +861,8 @@ class ssl_http_session
|
||||
, public std::enable_shared_from_this<ssl_http_session>
|
||||
{
|
||||
ssl_stream<tcp::socket> stream_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::strand<
|
||||
boost::asio::io_context::executor_type> strand_;
|
||||
bool eof_ = false;
|
||||
|
||||
public:
|
||||
@ -849,11 +873,11 @@ public:
|
||||
boost::beast::flat_buffer buffer,
|
||||
std::string const& doc_root)
|
||||
: http_session<ssl_http_session>(
|
||||
socket.get_io_service(),
|
||||
socket.get_executor().context(),
|
||||
std::move(buffer),
|
||||
doc_root)
|
||||
, stream_(std::move(socket), ctx)
|
||||
, strand_(stream_.get_io_service())
|
||||
, strand_(stream_.get_executor())
|
||||
{
|
||||
}
|
||||
|
||||
@ -880,18 +904,20 @@ public:
|
||||
on_timer({});
|
||||
|
||||
// Set the timer
|
||||
timer_.expires_from_now(std::chrono::seconds(15));
|
||||
timer_.expires_after(std::chrono::seconds(15));
|
||||
|
||||
// Perform the SSL handshake
|
||||
// Note, this is the buffered version of the handshake.
|
||||
stream_.async_handshake(
|
||||
ssl::stream_base::server,
|
||||
buffer_.data(),
|
||||
strand_.wrap(std::bind(
|
||||
&ssl_http_session::on_handshake,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&ssl_http_session::on_handshake,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
}
|
||||
void
|
||||
on_handshake(
|
||||
@ -917,14 +943,16 @@ public:
|
||||
eof_ = true;
|
||||
|
||||
// Set the timer
|
||||
timer_.expires_from_now(std::chrono::seconds(15));
|
||||
timer_.expires_after(std::chrono::seconds(15));
|
||||
|
||||
// Perform the SSL shutdown
|
||||
stream_.async_shutdown(
|
||||
strand_.wrap(std::bind(
|
||||
&ssl_http_session::on_shutdown,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&ssl_http_session::on_shutdown,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -962,7 +990,8 @@ class detect_session : public std::enable_shared_from_this<detect_session>
|
||||
{
|
||||
tcp::socket socket_;
|
||||
ssl::context& ctx_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::strand<
|
||||
boost::asio::io_context::executor_type> strand_;
|
||||
std::string const& doc_root_;
|
||||
boost::beast::flat_buffer buffer_;
|
||||
|
||||
@ -974,7 +1003,7 @@ public:
|
||||
std::string const& doc_root)
|
||||
: socket_(std::move(socket))
|
||||
, ctx_(ctx)
|
||||
, strand_(socket_.get_io_service())
|
||||
, strand_(socket_.get_executor())
|
||||
, doc_root_(doc_root)
|
||||
{
|
||||
}
|
||||
@ -986,11 +1015,13 @@ public:
|
||||
async_detect_ssl(
|
||||
socket_,
|
||||
buffer_,
|
||||
strand_.wrap(std::bind(
|
||||
&detect_session::on_detect,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&detect_session::on_detect,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
|
||||
}
|
||||
|
||||
@ -1029,13 +1060,13 @@ class listener : public std::enable_shared_from_this<listener>
|
||||
|
||||
public:
|
||||
listener(
|
||||
boost::asio::io_service& ios,
|
||||
boost::asio::io_context& ioc,
|
||||
ssl::context& ctx,
|
||||
tcp::endpoint endpoint,
|
||||
std::string const& doc_root)
|
||||
: ctx_(ctx)
|
||||
, acceptor_(ios)
|
||||
, socket_(ios)
|
||||
, acceptor_(ioc)
|
||||
, socket_(ioc)
|
||||
, doc_root_(doc_root)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
@ -1058,7 +1089,7 @@ public:
|
||||
|
||||
// Start listening for connections
|
||||
acceptor_.listen(
|
||||
boost::asio::socket_base::max_connections, ec);
|
||||
boost::asio::socket_base::max_listen_connections, ec);
|
||||
if(ec)
|
||||
{
|
||||
fail(ec, "listen");
|
||||
@ -1120,13 +1151,13 @@ int main(int argc, char* argv[])
|
||||
" advanced-server-flex 0.0.0.0 8080 . 1\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto const address = boost::asio::ip::address::from_string(argv[1]);
|
||||
auto const address = boost::asio::ip::make_address(argv[1]);
|
||||
auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||
std::string const doc_root = argv[3];
|
||||
auto const threads = std::max<std::size_t>(1, std::atoi(argv[4]));
|
||||
auto const threads = std::max<int>(1, std::atoi(argv[4]));
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios{threads};
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc{threads};
|
||||
|
||||
// The SSL context is required, and holds certificates
|
||||
ssl::context ctx{ssl::context::sslv23};
|
||||
@ -1136,7 +1167,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
// Create and launch a listening port
|
||||
std::make_shared<listener>(
|
||||
ios,
|
||||
ioc,
|
||||
ctx,
|
||||
tcp::endpoint{address, port},
|
||||
doc_root)->run();
|
||||
@ -1146,11 +1177,11 @@ int main(int argc, char* argv[])
|
||||
v.reserve(threads - 1);
|
||||
for(auto i = threads - 1; i > 0; --i)
|
||||
v.emplace_back(
|
||||
[&ios]
|
||||
[&ioc]
|
||||
{
|
||||
ios.run();
|
||||
ioc.run();
|
||||
});
|
||||
ios.run();
|
||||
ioc.run();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <boost/beast/http.hpp>
|
||||
#include <boost/beast/websocket.hpp>
|
||||
#include <boost/beast/version.hpp>
|
||||
#include <boost/asio/bind_executor.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
@ -214,7 +215,8 @@ fail(boost::system::error_code ec, char const* what)
|
||||
class websocket_session : public std::enable_shared_from_this<websocket_session>
|
||||
{
|
||||
websocket::stream<tcp::socket> ws_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::strand<
|
||||
boost::asio::io_context::executor_type> strand_;
|
||||
boost::asio::steady_timer timer_;
|
||||
boost::beast::multi_buffer buffer_;
|
||||
|
||||
@ -223,8 +225,8 @@ public:
|
||||
explicit
|
||||
websocket_session(tcp::socket socket)
|
||||
: ws_(std::move(socket))
|
||||
, strand_(ws_.get_io_service())
|
||||
, timer_(ws_.get_io_service(),
|
||||
, strand_(ws_.get_executor())
|
||||
, timer_(ws_.get_executor().context(),
|
||||
(std::chrono::steady_clock::time_point::max)())
|
||||
{
|
||||
}
|
||||
@ -239,15 +241,17 @@ public:
|
||||
on_timer({});
|
||||
|
||||
// Set the timer
|
||||
timer_.expires_from_now(std::chrono::seconds(15));
|
||||
timer_.expires_after(std::chrono::seconds(15));
|
||||
|
||||
// Accept the websocket handshake
|
||||
ws_.async_accept(
|
||||
req,
|
||||
strand_.wrap(std::bind(
|
||||
&websocket_session::on_accept,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&websocket_session::on_accept,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
}
|
||||
|
||||
// Called when the timer expires.
|
||||
@ -258,7 +262,7 @@ public:
|
||||
return fail(ec, "timer");
|
||||
|
||||
// Verify that the timer really expired since the deadline may have moved.
|
||||
if(timer_.expires_at() <= std::chrono::steady_clock::now())
|
||||
if(timer_.expiry() <= std::chrono::steady_clock::now())
|
||||
{
|
||||
// Closing the socket cancels all outstanding operations. They
|
||||
// will complete with boost::asio::error::operation_aborted
|
||||
@ -269,10 +273,12 @@ public:
|
||||
|
||||
// Wait on the timer
|
||||
timer_.async_wait(
|
||||
strand_.wrap(std::bind(
|
||||
&websocket_session::on_timer,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&websocket_session::on_timer,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -293,16 +299,18 @@ public:
|
||||
do_read()
|
||||
{
|
||||
// Set the timer
|
||||
timer_.expires_from_now(std::chrono::seconds(15));
|
||||
timer_.expires_after(std::chrono::seconds(15));
|
||||
|
||||
// Read a message into our buffer
|
||||
ws_.async_read(
|
||||
buffer_,
|
||||
strand_.wrap(std::bind(
|
||||
&websocket_session::on_read,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&websocket_session::on_read,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -327,11 +335,13 @@ public:
|
||||
ws_.text(ws_.got_text());
|
||||
ws_.async_write(
|
||||
buffer_.data(),
|
||||
strand_.wrap(std::bind(
|
||||
&websocket_session::on_write,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&websocket_session::on_write,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -432,10 +442,12 @@ class http_session : public std::enable_shared_from_this<http_session>
|
||||
http::async_write(
|
||||
self_.socket_,
|
||||
msg_,
|
||||
self_.strand_.wrap(std::bind(
|
||||
&http_session::on_write,
|
||||
self_.shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
boost::asio::bind_executor(
|
||||
self_.strand_,
|
||||
std::bind(
|
||||
&http_session::on_write,
|
||||
self_.shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
}
|
||||
};
|
||||
|
||||
@ -449,7 +461,8 @@ class http_session : public std::enable_shared_from_this<http_session>
|
||||
};
|
||||
|
||||
tcp::socket socket_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::strand<
|
||||
boost::asio::io_context::executor_type> strand_;
|
||||
boost::asio::steady_timer timer_;
|
||||
boost::beast::flat_buffer buffer_;
|
||||
std::string const& doc_root_;
|
||||
@ -463,8 +476,8 @@ public:
|
||||
tcp::socket socket,
|
||||
std::string const& doc_root)
|
||||
: socket_(std::move(socket))
|
||||
, strand_(socket_.get_io_service())
|
||||
, timer_(socket_.get_io_service(),
|
||||
, strand_(socket_.get_executor())
|
||||
, timer_(socket_.get_executor().context(),
|
||||
(std::chrono::steady_clock::time_point::max)())
|
||||
, doc_root_(doc_root)
|
||||
, queue_(*this)
|
||||
@ -486,14 +499,16 @@ public:
|
||||
do_read()
|
||||
{
|
||||
// Set the timer
|
||||
timer_.expires_from_now(std::chrono::seconds(15));
|
||||
timer_.expires_after(std::chrono::seconds(15));
|
||||
|
||||
// Read a request
|
||||
http::async_read(socket_, buffer_, req_,
|
||||
strand_.wrap(std::bind(
|
||||
&http_session::on_read,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&http_session::on_read,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
}
|
||||
|
||||
// Called when the timer expires.
|
||||
@ -504,7 +519,7 @@ public:
|
||||
return fail(ec, "timer");
|
||||
|
||||
// Verify that the timer really expired since the deadline may have moved.
|
||||
if(timer_.expires_at() <= std::chrono::steady_clock::now())
|
||||
if(timer_.expiry() <= std::chrono::steady_clock::now())
|
||||
{
|
||||
// Closing the socket cancels all outstanding operations. They
|
||||
// will complete with boost::asio::error::operation_aborted
|
||||
@ -515,10 +530,12 @@ public:
|
||||
|
||||
// Wait on the timer
|
||||
timer_.async_wait(
|
||||
strand_.wrap(std::bind(
|
||||
&http_session::on_timer,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&http_session::on_timer,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -599,11 +616,11 @@ class listener : public std::enable_shared_from_this<listener>
|
||||
|
||||
public:
|
||||
listener(
|
||||
boost::asio::io_service& ios,
|
||||
boost::asio::io_context& ioc,
|
||||
tcp::endpoint endpoint,
|
||||
std::string const& doc_root)
|
||||
: acceptor_(ios)
|
||||
, socket_(ios)
|
||||
: acceptor_(ioc)
|
||||
, socket_(ioc)
|
||||
, doc_root_(doc_root)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
@ -626,7 +643,7 @@ public:
|
||||
|
||||
// Start listening for connections
|
||||
acceptor_.listen(
|
||||
boost::asio::socket_base::max_connections, ec);
|
||||
boost::asio::socket_base::max_listen_connections, ec);
|
||||
if(ec)
|
||||
{
|
||||
fail(ec, "listen");
|
||||
@ -687,17 +704,17 @@ int main(int argc, char* argv[])
|
||||
" advanced-server 0.0.0.0 8080 . 1\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto const address = boost::asio::ip::address::from_string(argv[1]);
|
||||
auto const address = boost::asio::ip::make_address(argv[1]);
|
||||
auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||
std::string const doc_root = argv[3];
|
||||
auto const threads = std::max<std::size_t>(1, std::atoi(argv[4]));
|
||||
auto const threads = std::max<int>(1, std::atoi(argv[4]));
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios{threads};
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc{threads};
|
||||
|
||||
// Create and launch a listening port
|
||||
std::make_shared<listener>(
|
||||
ios,
|
||||
ioc,
|
||||
tcp::endpoint{address, port},
|
||||
doc_root)->run();
|
||||
|
||||
@ -706,11 +723,11 @@ int main(int argc, char* argv[])
|
||||
v.reserve(threads - 1);
|
||||
for(auto i = threads - 1; i > 0; --i)
|
||||
v.emplace_back(
|
||||
[&ios]
|
||||
[&ioc]
|
||||
{
|
||||
ios.run();
|
||||
ioc.run();
|
||||
});
|
||||
ios.run();
|
||||
ioc.run();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -61,7 +61,8 @@ is_ssl_handshake(
|
||||
ConstBufferSequence const& buffers)
|
||||
{
|
||||
// Make sure buffers meets the requirements
|
||||
static_assert(boost::beast::is_const_buffer_sequence<ConstBufferSequence>::value,
|
||||
static_assert(
|
||||
boost::asio::is_const_buffer_sequence<ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
|
||||
// We need at least one byte to really do anything
|
||||
@ -135,7 +136,8 @@ detect_ssl(
|
||||
// Make sure arguments meet the requirements
|
||||
static_assert(beast::is_sync_read_stream<SyncReadStream>::value,
|
||||
"SyncReadStream requirements not met");
|
||||
static_assert(beast::is_dynamic_buffer<DynamicBuffer>::value,
|
||||
static_assert(
|
||||
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||
"DynamicBuffer requirements not met");
|
||||
|
||||
// Loop until an error occurs or we get a definitive answer
|
||||
@ -219,15 +221,15 @@ detect_ssl(
|
||||
Regardless of whether the asynchronous operation completes
|
||||
immediately or not, the handler will not be invoked from within
|
||||
this function. Invocation of the handler will be performed in a
|
||||
manner equivalent to using `boost::asio::io_service::post`.
|
||||
manner equivalent to using `boost::asio::io_context::post`.
|
||||
*/
|
||||
template<
|
||||
class AsyncReadStream,
|
||||
class DynamicBuffer,
|
||||
class CompletionToken>
|
||||
boost::beast::async_return_type< /*< The [link beast.ref.boost__beast__async_return_type `async_return_type`] customizes the return value based on the completion token >*/
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE( /*< `BOOST_ASIO_INITFN_RESULT_TYPE` customizes the return value based on the completion token >*/
|
||||
CompletionToken,
|
||||
void(boost::beast::error_code, boost::tribool)> /*< This is the signature for the completion handler >*/
|
||||
void(boost::beast::error_code, boost::tribool)) /*< This is the signature for the completion handler >*/
|
||||
async_detect_ssl(
|
||||
AsyncReadStream& stream,
|
||||
DynamicBuffer& buffer,
|
||||
@ -249,9 +251,9 @@ template<
|
||||
class AsyncReadStream,
|
||||
class DynamicBuffer,
|
||||
class CompletionToken>
|
||||
boost::beast::async_return_type<
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||
CompletionToken,
|
||||
void(boost::beast::error_code, boost::tribool)>
|
||||
void(boost::beast::error_code, boost::tribool))
|
||||
async_detect_ssl(
|
||||
AsyncReadStream& stream,
|
||||
DynamicBuffer& buffer,
|
||||
@ -262,26 +264,29 @@ async_detect_ssl(
|
||||
// Make sure arguments meet the requirements
|
||||
static_assert(beast::is_async_read_stream<AsyncReadStream>::value,
|
||||
"SyncReadStream requirements not met");
|
||||
static_assert(beast::is_dynamic_buffer<DynamicBuffer>::value,
|
||||
static_assert(
|
||||
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||
"DynamicBuffer 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<
|
||||
boost::asio::async_completion<
|
||||
CompletionToken, void(beast::error_code, boost::tribool)> init{token};
|
||||
|
||||
// Create the composed operation and launch it. This is a constructor
|
||||
// call followed by invocation of operator(). We use handler_type
|
||||
// call followed by invocation of operator(). We use BOOST_ASIO_HANDLER_TYPE
|
||||
// to convert the completion token into the correct handler type,
|
||||
// allowing user defined specializations of the async result template
|
||||
// to take effect.
|
||||
//
|
||||
detect_ssl_op<AsyncReadStream, DynamicBuffer, beast::handler_type<
|
||||
CompletionToken, void(beast::error_code, boost::tribool)>>{
|
||||
stream, buffer, init.completion_handler}(
|
||||
beast::error_code{}, 0);
|
||||
detect_ssl_op<
|
||||
AsyncReadStream,
|
||||
DynamicBuffer,
|
||||
BOOST_ASIO_HANDLER_TYPE(
|
||||
CompletionToken, void(beast::error_code, boost::tribool))>{
|
||||
stream, buffer, 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, boost::tribool> if
|
||||
@ -336,6 +341,35 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
// Associated allocator support. This is Asio's system for
|
||||
// allowing the final completion handler to customize the
|
||||
// memory allocation strategy used for composed operation
|
||||
// states. A composed operation needs to use the same allocator
|
||||
// as the final handler. These declarations achieve that.
|
||||
|
||||
using allocator_type =
|
||||
boost::asio::associated_allocator_t<Handler>;
|
||||
|
||||
allocator_type
|
||||
get_allocator() const noexcept
|
||||
{
|
||||
return boost::asio::get_associated_allocator(handler_);
|
||||
}
|
||||
|
||||
// Executor hook. This is Asio's system for customizing the
|
||||
// manner in which asynchronous completion handlers are invoked.
|
||||
// A composed operation needs to use the same executor to invoke
|
||||
// intermediate completion handlers as that used to invoke the
|
||||
// final handler.
|
||||
|
||||
using executor_type = boost::asio::associated_executor_t<
|
||||
Handler, decltype(stream_.get_executor())>;
|
||||
|
||||
executor_type get_executor() const noexcept
|
||||
{
|
||||
return boost::asio::get_associated_executor(handler_, stream_.get_executor());
|
||||
}
|
||||
|
||||
// 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 two, it means
|
||||
@ -358,34 +392,6 @@ public:
|
||||
asio_handler_is_continuation(std::addressof(op->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, detect_ssl_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_allocate;
|
||||
return asio_handler_allocate(size, std::addressof(op->handler_));
|
||||
}
|
||||
|
||||
friend void asio_handler_deallocate(void* p, std::size_t size, detect_ssl_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
return asio_handler_deallocate(p, size, std::addressof(op->handler_));
|
||||
}
|
||||
|
||||
template<class Function>
|
||||
friend void asio_handler_invoke(Function&& f, detect_ssl_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_invoke;
|
||||
return asio_handler_invoke(f, std::addressof(op->handler_));
|
||||
}
|
||||
|
||||
// Our main entry point. This will get called as our
|
||||
// intermediate operations complete. Definition below.
|
||||
//
|
||||
@ -424,12 +430,13 @@ operator()(boost::beast::error_code ec, std::size_t bytes_transferred)
|
||||
// We need to invoke the handler, but the guarantee
|
||||
// is that the handler will not be called before the
|
||||
// call to async_detect_ssl returns, so we must post
|
||||
// the operation to the io_service. The helper function
|
||||
// the operation to the executor. The helper function
|
||||
// `bind_handler` lets us bind arguments in a safe way
|
||||
// that preserves the type customization hooks of the
|
||||
// original handler.
|
||||
step_ = 1;
|
||||
return stream_.get_io_service().post(
|
||||
return boost::asio::post(
|
||||
stream_.get_executor(),
|
||||
beast::bind_handler(std::move(*this), ec, 0));
|
||||
}
|
||||
|
||||
|
@ -10,21 +10,21 @@
|
||||
#ifndef BOOST_BEAST_EXAMPLE_COMMON_SESSION_ALLOC_HPP
|
||||
#define BOOST_BEAST_EXAMPLE_COMMON_SESSION_ALLOC_HPP
|
||||
|
||||
#include <boost/asio/handler_alloc_hook.hpp>
|
||||
#include <boost/asio/associated_allocator.hpp>
|
||||
#include <boost/asio/associated_executor.hpp>
|
||||
#include <boost/asio/handler_continuation_hook.hpp>
|
||||
#include <boost/asio/handler_invoke_hook.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class Context>
|
||||
class session_alloc_base
|
||||
{
|
||||
template<class Handler>
|
||||
class wrapped_handler;
|
||||
|
||||
protected:
|
||||
class pool_t
|
||||
{
|
||||
using hook_type =
|
||||
@ -78,23 +78,18 @@ class session_alloc_base
|
||||
boost::intrusive::constant_time_size<
|
||||
true>>::type;
|
||||
|
||||
Context* ctx_;
|
||||
std::size_t refs_ = 1; // shared count
|
||||
std::size_t high_ = 0; // highest used
|
||||
std::size_t size_ = 0; // size of buf_
|
||||
char* buf_ = nullptr; // a large block
|
||||
list_type list_; // list of allocations
|
||||
|
||||
explicit
|
||||
pool_t(Context* ctx)
|
||||
: ctx_(ctx)
|
||||
{
|
||||
}
|
||||
pool_t() = default;
|
||||
|
||||
public:
|
||||
static
|
||||
pool_t&
|
||||
construct(Context* ctx);
|
||||
construct();
|
||||
|
||||
~pool_t();
|
||||
|
||||
@ -110,73 +105,178 @@ class session_alloc_base
|
||||
void
|
||||
dealloc(void* pv, std::size_t n);
|
||||
};
|
||||
|
||||
pool_t& pool_;
|
||||
|
||||
public:
|
||||
session_alloc_base& operator=(session_alloc_base const&) = delete;
|
||||
|
||||
~session_alloc_base()
|
||||
{
|
||||
pool_.release();
|
||||
}
|
||||
|
||||
session_alloc_base()
|
||||
: pool_(pool_t::construct(nullptr))
|
||||
{
|
||||
static_assert(std::is_same<Context, std::nullptr_t>::value,
|
||||
"Context requirements not met");
|
||||
}
|
||||
|
||||
session_alloc_base(session_alloc_base const& other)
|
||||
: pool_(other.pool_.addref())
|
||||
{
|
||||
}
|
||||
|
||||
template<class DeducedContext, class = typename
|
||||
std::enable_if<! std::is_same<
|
||||
session_alloc_base<Context>,
|
||||
typename std::decay<DeducedContext>::type
|
||||
>::value>::type>
|
||||
explicit
|
||||
session_alloc_base(DeducedContext& ctx)
|
||||
: pool_(pool_t::construct(std::addressof(ctx)))
|
||||
{
|
||||
static_assert(! std::is_same<Context, std::nullptr_t>::value,
|
||||
"Context requirements not met");
|
||||
}
|
||||
|
||||
template<class Handler>
|
||||
wrapped_handler<typename std::decay<Handler>::type>
|
||||
wrap(Handler&& handler)
|
||||
{
|
||||
return wrapped_handler<
|
||||
typename std::decay<Handler>::type>(
|
||||
std::forward<Handler>(handler), *this);
|
||||
}
|
||||
|
||||
protected:
|
||||
void*
|
||||
alloc(std::size_t n)
|
||||
{
|
||||
return pool_.alloc(n);
|
||||
}
|
||||
|
||||
void
|
||||
dealloc(void* p, std::size_t n)
|
||||
{
|
||||
pool_.dealloc(p, n);
|
||||
}
|
||||
};
|
||||
|
||||
template<class Context>
|
||||
auto
|
||||
session_alloc_base<Context>::
|
||||
pool_t::
|
||||
construct() ->
|
||||
pool_t&
|
||||
{
|
||||
return *(new pool_t);
|
||||
}
|
||||
|
||||
template<class Context>
|
||||
session_alloc_base<Context>::
|
||||
pool_t::
|
||||
~pool_t()
|
||||
{
|
||||
BOOST_ASSERT(list_.size() == 0);
|
||||
if(buf_)
|
||||
delete[] buf_;
|
||||
}
|
||||
|
||||
template<class Context>
|
||||
auto
|
||||
session_alloc_base<Context>::
|
||||
pool_t::
|
||||
addref() ->
|
||||
pool_t&
|
||||
{
|
||||
++refs_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Context>
|
||||
void
|
||||
session_alloc_base<Context>::
|
||||
pool_t::
|
||||
release()
|
||||
{
|
||||
if(--refs_)
|
||||
return;
|
||||
delete this;
|
||||
}
|
||||
|
||||
template<class Context>
|
||||
void*
|
||||
session_alloc_base<Context>::
|
||||
pool_t::
|
||||
alloc(std::size_t n)
|
||||
{
|
||||
if(list_.empty() && size_ < high_)
|
||||
{
|
||||
if(buf_)
|
||||
delete[] buf_;
|
||||
buf_ = new char[high_];
|
||||
size_ = high_;
|
||||
}
|
||||
if(buf_)
|
||||
{
|
||||
char* end;
|
||||
std::size_t used;
|
||||
if(list_.empty())
|
||||
{
|
||||
end = buf_;
|
||||
used = sizeof(element) + n;
|
||||
}
|
||||
else
|
||||
{
|
||||
end = list_.back().end();
|
||||
used = list_.back().used() +
|
||||
sizeof(element) + n;
|
||||
}
|
||||
if(end >= buf_ && end +
|
||||
sizeof(element) + n <= buf_ + size_)
|
||||
{
|
||||
auto& e = *new(end) element{n, used};
|
||||
list_.push_back(e);
|
||||
high_ = (std::max)(high_, used);
|
||||
return e.data();
|
||||
}
|
||||
}
|
||||
std::size_t const used =
|
||||
sizeof(element) + n + (
|
||||
buf_ && ! list_.empty() ?
|
||||
list_.back().used() : 0);
|
||||
auto& e = *new(new char[sizeof(element) + n]) element{n, used};
|
||||
list_.push_back(e);
|
||||
high_ = (std::max)(high_, used);
|
||||
return e.data();
|
||||
}
|
||||
|
||||
template<class Context>
|
||||
void
|
||||
session_alloc_base<Context>::
|
||||
pool_t::
|
||||
dealloc(void* pv, std::size_t n)
|
||||
{
|
||||
auto& e = *(reinterpret_cast<element*>(pv) - 1);
|
||||
BOOST_ASSERT(e.size() == n);
|
||||
if( (e.end() > buf_ + size_) ||
|
||||
reinterpret_cast<char*>(&e) < buf_)
|
||||
{
|
||||
list_.erase(list_.iterator_to(e));
|
||||
e.~element();
|
||||
delete[] reinterpret_cast<char*>(&e);
|
||||
return;
|
||||
}
|
||||
list_.erase(list_.iterator_to(e));
|
||||
e.~element();
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class T, class Context = std::nullptr_t>
|
||||
class session_alloc : public session_alloc_base<Context>
|
||||
template<class T>
|
||||
class session_alloc
|
||||
: private detail::session_alloc_base<void>
|
||||
{
|
||||
template<class U, class C>
|
||||
template<class U>
|
||||
friend class session_alloc;
|
||||
|
||||
template<class Handler>
|
||||
class wrapped_handler
|
||||
{
|
||||
// Can't friend partial specializations,
|
||||
// so we just friend the whole thing.
|
||||
template<class T, class Executor>
|
||||
friend struct boost::asio::associated_executor;
|
||||
|
||||
Handler h_;
|
||||
session_alloc<char> alloc_;
|
||||
|
||||
public:
|
||||
wrapped_handler(wrapped_handler&&) = default;
|
||||
wrapped_handler(wrapped_handler const&) = default;
|
||||
|
||||
template<class DeducedHandler>
|
||||
wrapped_handler(
|
||||
DeducedHandler&& h,
|
||||
session_alloc const& alloc)
|
||||
: h_(std::forward<DeducedHandler>(h))
|
||||
, alloc_(alloc)
|
||||
{
|
||||
}
|
||||
|
||||
using allocator_type = session_alloc<char>;
|
||||
|
||||
allocator_type
|
||||
get_allocator() const noexcept;
|
||||
|
||||
template<class... Args>
|
||||
void
|
||||
operator()(Args&&... args) const
|
||||
{
|
||||
h_(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
asio_handler_is_continuation(wrapped_handler* w)
|
||||
{
|
||||
using boost::asio::asio_handler_is_continuation;
|
||||
return asio_handler_is_continuation(std::addressof(w->h_));
|
||||
}
|
||||
};
|
||||
|
||||
using pool_t = typename
|
||||
detail::session_alloc_base<void>::pool_t;
|
||||
|
||||
pool_t& pool_;
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
using is_always_equal = std::false_type;
|
||||
@ -193,21 +293,32 @@ public:
|
||||
using other = session_alloc<U>;
|
||||
};
|
||||
|
||||
session_alloc() = default;
|
||||
session_alloc(session_alloc const&) = default;
|
||||
session_alloc& operator=(session_alloc const&) = delete;
|
||||
|
||||
~session_alloc()
|
||||
{
|
||||
pool_.release();
|
||||
}
|
||||
|
||||
session_alloc()
|
||||
: pool_(pool_t::construct())
|
||||
{
|
||||
}
|
||||
|
||||
session_alloc(session_alloc const& other) noexcept
|
||||
: pool_(other.pool_.addref())
|
||||
{
|
||||
}
|
||||
|
||||
template<class U>
|
||||
session_alloc(session_alloc<U> const& other)
|
||||
: session_alloc_base<Context>(static_cast<
|
||||
session_alloc_base<Context> const&>(other))
|
||||
session_alloc(session_alloc<U> const& other) noexcept
|
||||
: pool_(other.pool_)
|
||||
{
|
||||
}
|
||||
|
||||
explicit
|
||||
session_alloc(Context& ctx)
|
||||
: session_alloc_base<Context>(ctx)
|
||||
{
|
||||
}
|
||||
template<class Handler>
|
||||
wrapped_handler<typename std::decay<Handler>::type>
|
||||
wrap(Handler&& handler);
|
||||
|
||||
value_type*
|
||||
allocate(size_type n)
|
||||
@ -257,209 +368,67 @@ public:
|
||||
{
|
||||
return ! (lhs == rhs);
|
||||
}
|
||||
|
||||
protected:
|
||||
void*
|
||||
alloc(std::size_t n)
|
||||
{
|
||||
return pool_.alloc(n);
|
||||
}
|
||||
|
||||
void
|
||||
dealloc(void* p, std::size_t n)
|
||||
{
|
||||
pool_.dealloc(p, n);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class Context>
|
||||
template<class T>
|
||||
template<class Handler>
|
||||
class session_alloc_base<Context>::wrapped_handler
|
||||
auto
|
||||
session_alloc<T>::
|
||||
wrapped_handler<Handler>::
|
||||
get_allocator() const noexcept ->
|
||||
allocator_type
|
||||
{
|
||||
Handler h_;
|
||||
session_alloc_base alloc_;
|
||||
|
||||
void*
|
||||
alloc(std::size_t size)
|
||||
{
|
||||
return alloc_.alloc(size);
|
||||
}
|
||||
|
||||
void
|
||||
dealloc(void* p, std::size_t size)
|
||||
{
|
||||
alloc_.dealloc(p, size);
|
||||
}
|
||||
|
||||
public:
|
||||
wrapped_handler(wrapped_handler&&) = default;
|
||||
wrapped_handler(wrapped_handler const&) = default;
|
||||
|
||||
template<class DeducedHandler>
|
||||
explicit
|
||||
wrapped_handler(DeducedHandler&& h,
|
||||
session_alloc_base const& alloc)
|
||||
: h_(std::forward<DeducedHandler>(h))
|
||||
, alloc_(alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
void
|
||||
operator()(Args&&... args) const
|
||||
{
|
||||
h_(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
friend
|
||||
void*
|
||||
asio_handler_allocate(
|
||||
std::size_t size, wrapped_handler* w)
|
||||
{
|
||||
return w->alloc(size);
|
||||
}
|
||||
|
||||
friend
|
||||
void
|
||||
asio_handler_deallocate(
|
||||
void* p, std::size_t size, wrapped_handler* w)
|
||||
{
|
||||
w->dealloc(p, size);
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
asio_handler_is_continuation(wrapped_handler* w)
|
||||
{
|
||||
using boost::asio::asio_handler_is_continuation;
|
||||
return asio_handler_is_continuation(std::addressof(w->h_));
|
||||
}
|
||||
|
||||
template<class F>
|
||||
friend
|
||||
void
|
||||
asio_handler_invoke(F&& f, wrapped_handler* w)
|
||||
{
|
||||
using boost::asio::asio_handler_invoke;
|
||||
asio_handler_invoke(
|
||||
f, std::addressof(w->h_));
|
||||
}
|
||||
};
|
||||
return alloc_;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class Context>
|
||||
template<class T>
|
||||
template<class Handler>
|
||||
auto
|
||||
session_alloc_base<Context>::
|
||||
pool_t::
|
||||
construct(Context* ctx) ->
|
||||
pool_t&
|
||||
session_alloc<T>::
|
||||
wrap(Handler&& handler) ->
|
||||
wrapped_handler<typename std::decay<Handler>::type>
|
||||
{
|
||||
using boost::asio::asio_handler_allocate;
|
||||
return *new(asio_handler_allocate(
|
||||
sizeof(pool_t), ctx)) pool_t{ctx};
|
||||
return wrapped_handler<
|
||||
typename std::decay<Handler>::type>(
|
||||
std::forward<Handler>(handler), *this);
|
||||
}
|
||||
|
||||
template<class Context>
|
||||
session_alloc_base<Context>::
|
||||
pool_t::
|
||||
~pool_t()
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
template<class T, class Handler, class Executor>
|
||||
struct associated_executor<
|
||||
session_alloc<T>::wrapped_handler<Handler>, Executor>
|
||||
{
|
||||
BOOST_ASSERT(list_.size() == 0);
|
||||
if(buf_)
|
||||
using type = typename
|
||||
associated_executor<Handler, Executor>::type;
|
||||
|
||||
static
|
||||
type
|
||||
get(session_alloc<T>::wrapped_handler<Handler> const& h,
|
||||
Executor const& ex = Executor()) noexcept
|
||||
{
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
asio_handler_deallocate(buf_, size_, ctx_);
|
||||
return associated_executor<
|
||||
Handler, Executor>::get(h.h_, ex);
|
||||
}
|
||||
}
|
||||
|
||||
template<class Context>
|
||||
auto
|
||||
session_alloc_base<Context>::
|
||||
pool_t::
|
||||
addref() ->
|
||||
pool_t&
|
||||
{
|
||||
++refs_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Context>
|
||||
void
|
||||
session_alloc_base<Context>::
|
||||
pool_t::
|
||||
release()
|
||||
{
|
||||
if(--refs_)
|
||||
return;
|
||||
this->~pool_t();
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
asio_handler_deallocate(this, sizeof(*this), ctx_);
|
||||
}
|
||||
|
||||
template<class Context>
|
||||
void*
|
||||
session_alloc_base<Context>::
|
||||
pool_t::
|
||||
alloc(std::size_t n)
|
||||
{
|
||||
if(list_.empty() && size_ < high_)
|
||||
{
|
||||
if(buf_)
|
||||
{
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
asio_handler_deallocate(buf_, size_, ctx_);
|
||||
}
|
||||
using boost::asio::asio_handler_allocate;
|
||||
buf_ = reinterpret_cast<char*>(
|
||||
asio_handler_allocate(high_, ctx_));
|
||||
size_ = high_;
|
||||
}
|
||||
if(buf_)
|
||||
{
|
||||
char* end;
|
||||
std::size_t used;
|
||||
if(list_.empty())
|
||||
{
|
||||
end = buf_;
|
||||
used = sizeof(element) + n;
|
||||
}
|
||||
else
|
||||
{
|
||||
end = list_.back().end();
|
||||
used = list_.back().used() +
|
||||
sizeof(element) + n;
|
||||
}
|
||||
if(end >= buf_ && end +
|
||||
sizeof(element) + n <= buf_ + size_)
|
||||
{
|
||||
auto& e = *new(end) element{n, used};
|
||||
list_.push_back(e);
|
||||
high_ = (std::max)(high_, used);
|
||||
return e.data();
|
||||
}
|
||||
}
|
||||
std::size_t const used =
|
||||
sizeof(element) + n + (
|
||||
buf_ && ! list_.empty() ?
|
||||
list_.back().used() : 0);
|
||||
using boost::asio::asio_handler_allocate;
|
||||
auto& e = *new(asio_handler_allocate(
|
||||
sizeof(element) + n, ctx_)) element{n, used};
|
||||
list_.push_back(e);
|
||||
high_ = (std::max)(high_, used);
|
||||
return e.data();
|
||||
}
|
||||
|
||||
template<class Context>
|
||||
void
|
||||
session_alloc_base<Context>::
|
||||
pool_t::
|
||||
dealloc(void* pv, std::size_t n)
|
||||
{
|
||||
auto& e = *(reinterpret_cast<element*>(pv) - 1);
|
||||
BOOST_ASSERT(e.size() == n);
|
||||
if( (e.end() > buf_ + size_) ||
|
||||
reinterpret_cast<char*>(&e) < buf_)
|
||||
{
|
||||
list_.erase(list_.iterator_to(e));
|
||||
e.~element();
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
asio_handler_deallocate(
|
||||
&e, sizeof(e) + n, ctx_);
|
||||
return;
|
||||
}
|
||||
list_.erase(list_.iterator_to(e));
|
||||
e.~element();
|
||||
}
|
||||
};
|
||||
} // asio
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
|
@ -52,9 +52,6 @@ public:
|
||||
/// Structure for use with deprecated impl_type.
|
||||
using impl_struct = typename stream_type::impl_struct;
|
||||
|
||||
/// (Deprecated: Use native_handle_type.) The underlying implementation type.
|
||||
using impl_type = typename stream_type::impl_type;
|
||||
|
||||
/// The type of the next layer.
|
||||
using next_layer_type = typename stream_type::next_layer_type;
|
||||
|
||||
@ -64,14 +61,16 @@ public:
|
||||
ssl_stream(
|
||||
boost::asio::ip::tcp::socket socket,
|
||||
boost::asio::ssl::context& ctx)
|
||||
: p_(new stream_type{socket.get_io_service(), ctx})
|
||||
: p_(new stream_type{
|
||||
socket.get_executor().context(), ctx})
|
||||
, ctx_(&ctx)
|
||||
{
|
||||
p_->next_layer() = std::move(socket);
|
||||
}
|
||||
|
||||
ssl_stream(ssl_stream&& other)
|
||||
: p_(new stream_type(other.get_io_service(), *other.ctx_))
|
||||
: p_(new stream_type(
|
||||
other.get_executor().context(), *other.ctx_))
|
||||
, ctx_(other.ctx_)
|
||||
{
|
||||
using std::swap;
|
||||
@ -80,8 +79,8 @@ public:
|
||||
|
||||
ssl_stream& operator=(ssl_stream&& other)
|
||||
{
|
||||
std::unique_ptr<stream_type> p(
|
||||
new stream_type{other.get_io_service(), other.ctx_});
|
||||
std::unique_ptr<stream_type> p(new stream_type{
|
||||
other.get_executor().context(), other.ctx_});
|
||||
using std::swap;
|
||||
swap(p_, p);
|
||||
swap(p_, other.p_);
|
||||
@ -89,10 +88,10 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
boost::asio::io_service&
|
||||
get_io_service()
|
||||
decltype(p_->get_executor())
|
||||
get_executor() noexcept
|
||||
{
|
||||
return p_->get_io_service();
|
||||
return p_->get_executor();
|
||||
}
|
||||
|
||||
native_handle_type
|
||||
@ -101,12 +100,6 @@ public:
|
||||
return p_->native_handle();
|
||||
}
|
||||
|
||||
impl_type
|
||||
impl()
|
||||
{
|
||||
return p_->impl();
|
||||
}
|
||||
|
||||
next_layer_type const&
|
||||
next_layer() const
|
||||
{
|
||||
|
@ -1,230 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2016-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)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/beast
|
||||
//
|
||||
|
||||
#ifndef BOOST_BEAST_EXAMPLE_COMMON_WRITE_MSG_HPP
|
||||
#define BOOST_BEAST_EXAMPLE_COMMON_WRITE_MSG_HPP
|
||||
|
||||
#include <boost/beast/core/async_result.hpp>
|
||||
#include <boost/beast/core/handler_ptr.hpp>
|
||||
#include <boost/beast/core/type_traits.hpp>
|
||||
#include <boost/beast/http/message.hpp>
|
||||
#include <boost/beast/http/write.hpp>
|
||||
#include <boost/beast/http/type_traits.hpp>
|
||||
#include <boost/asio/handler_alloc_hook.hpp>
|
||||
#include <boost/asio/handler_continuation_hook.hpp>
|
||||
#include <boost/asio/handler_invoke_hook.hpp>
|
||||
|
||||
namespace detail {
|
||||
|
||||
/** Composed operation to send an HTTP message
|
||||
|
||||
This implements the composed operation needed for the
|
||||
@ref async_write_msg function.
|
||||
*/
|
||||
template<
|
||||
class AsyncWriteStream,
|
||||
class Handler,
|
||||
bool isRequest, class Body, class Fields>
|
||||
class write_msg_op
|
||||
{
|
||||
// This composed operation has a state which is not trivial
|
||||
// to copy (msg) so we need to store the state in an allocated
|
||||
// object.
|
||||
//
|
||||
struct data
|
||||
{
|
||||
// The stream we are writing to
|
||||
AsyncWriteStream& stream;
|
||||
|
||||
// The message we are sending. Note that this composed
|
||||
// operation takes ownership of the message and destroys
|
||||
// it when it is done.
|
||||
//
|
||||
boost::beast::http::message<isRequest, Body, Fields> msg;
|
||||
|
||||
// Serializer for the message
|
||||
boost::beast::http::serializer<isRequest, Body, Fields> sr;
|
||||
|
||||
data(
|
||||
Handler& handler,
|
||||
AsyncWriteStream& stream_,
|
||||
boost::beast::http::message<isRequest, Body, Fields>&& msg_)
|
||||
: stream(stream_)
|
||||
, msg(std::move(msg_))
|
||||
, sr(msg)
|
||||
{
|
||||
boost::ignore_unused(handler);
|
||||
}
|
||||
};
|
||||
|
||||
// `handler_ptr` is a utility which helps to manage a composed
|
||||
// operation's state. It is similar to a shared pointer, but
|
||||
// it uses handler allocation hooks to allocate and free memory,
|
||||
// and it also helps to meet Asio's deallocate-before-invocation
|
||||
// guarantee.
|
||||
//
|
||||
boost::beast::handler_ptr<data, Handler> d_;
|
||||
|
||||
public:
|
||||
// Asio can move and copy the handler, we support both
|
||||
write_msg_op(write_msg_op&&) = default;
|
||||
write_msg_op(write_msg_op const&) = default;
|
||||
|
||||
// Constructor
|
||||
//
|
||||
// We take the handler as a template type to
|
||||
// support both const and rvalue references.
|
||||
//
|
||||
template<
|
||||
class DeducedHandler,
|
||||
class... Args>
|
||||
write_msg_op(
|
||||
DeducedHandler&& h,
|
||||
AsyncWriteStream& s,
|
||||
Args&&... args)
|
||||
: d_(std::forward<DeducedHandler>(h),
|
||||
s, std::forward<Args>(args)...)
|
||||
{
|
||||
}
|
||||
|
||||
// Entry point
|
||||
//
|
||||
// The initiation function calls this to start the operation
|
||||
//
|
||||
void
|
||||
operator()()
|
||||
{
|
||||
auto& d = *d_;
|
||||
boost::beast::http::async_write(
|
||||
d.stream, d.sr, std::move(*this));
|
||||
}
|
||||
|
||||
// Completion handler
|
||||
//
|
||||
// This gets called when boost::beast::http::async_write completes
|
||||
//
|
||||
void
|
||||
operator()(boost::beast::error_code ec)
|
||||
{
|
||||
d_.invoke(ec);
|
||||
}
|
||||
|
||||
//
|
||||
// These hooks are necessary for Asio
|
||||
//
|
||||
// The meaning is explained in the Beast documentation
|
||||
//
|
||||
|
||||
friend
|
||||
void* asio_handler_allocate(
|
||||
std::size_t size, write_msg_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_allocate;
|
||||
return asio_handler_allocate(
|
||||
size, std::addressof(op->d_.handler()));
|
||||
}
|
||||
|
||||
friend
|
||||
void asio_handler_deallocate(
|
||||
void* p, std::size_t size, write_msg_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
asio_handler_deallocate(
|
||||
p, size, std::addressof(op->d_.handler()));
|
||||
}
|
||||
|
||||
friend
|
||||
bool asio_handler_is_continuation(write_msg_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_is_continuation;
|
||||
return asio_handler_is_continuation(std::addressof(op->d_.handler()));
|
||||
}
|
||||
|
||||
template<class Function>
|
||||
friend
|
||||
void asio_handler_invoke(Function&& f, write_msg_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_invoke;
|
||||
asio_handler_invoke(
|
||||
f, std::addressof(op->d_.handler()));
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
|
||||
/** Write an HTTP message to a stream asynchronously
|
||||
|
||||
This function is used to write a complete message to a stream asynchronously
|
||||
using HTTP/1. The function call always returns immediately. The asynchronous
|
||||
operation will continue until one of the following conditions is true:
|
||||
|
||||
@li The entire message is written.
|
||||
|
||||
@li An error occurs.
|
||||
|
||||
This operation is implemented in terms of zero or more calls to the stream's
|
||||
`async_write_some` function, and is known as a <em>composed operation</em>.
|
||||
The program must ensure that the stream performs no other write operations
|
||||
until this operation completes. The algorithm will use a temporary
|
||||
@ref serializer to produce buffers. If the semantics of the message
|
||||
indicate that the connection should be closed after the message is sent,
|
||||
the error delivered by this function
|
||||
will be @ref error::end_of_stream
|
||||
|
||||
@param stream The stream to which the data is to be written.
|
||||
The type must support the @b AsyncWriteStream concept.
|
||||
|
||||
@param msg The message to write. The function will take ownership
|
||||
of the object as if by move constrction.
|
||||
|
||||
@param handler The handler to be called when the operation
|
||||
completes. Copies will be made of the handler as required.
|
||||
The equivalent function signature of the handler must be:
|
||||
@code void handler(
|
||||
error_code const& error // result of operation
|
||||
); @endcode
|
||||
Regardless of whether the asynchronous operation completes
|
||||
immediately or not, the handler will not be invoked from within
|
||||
this function. Invocation of the handler will be performed in a
|
||||
manner equivalent to using `boost::asio::io_service::post`.
|
||||
*/
|
||||
template<
|
||||
class AsyncWriteStream,
|
||||
bool isRequest, class Body, class Fields,
|
||||
class WriteHandler>
|
||||
boost::beast::async_return_type<WriteHandler, void(boost::beast::error_code)>
|
||||
async_write_msg(
|
||||
AsyncWriteStream& stream,
|
||||
boost::beast::http::message<isRequest, Body, Fields>&& msg,
|
||||
WriteHandler&& handler)
|
||||
{
|
||||
static_assert(
|
||||
boost::beast::is_async_write_stream<AsyncWriteStream>::value,
|
||||
"AsyncWriteStream requirements not met");
|
||||
|
||||
static_assert(boost::beast::http::is_body<Body>::value,
|
||||
"Body requirements not met");
|
||||
|
||||
static_assert(boost::beast::http::is_body_reader<Body>::value,
|
||||
"BodyReader requirements not met");
|
||||
|
||||
boost::beast::async_completion<WriteHandler, void(boost::beast::error_code)> init{handler};
|
||||
|
||||
::detail::write_msg_op<
|
||||
AsyncWriteStream,
|
||||
boost::beast::handler_type<WriteHandler, void(boost::beast::error_code)>,
|
||||
isRequest, Body, Fields>{
|
||||
init.completion_handler,
|
||||
stream,
|
||||
std::move(msg)}();
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
|
||||
#endif
|
@ -62,7 +62,8 @@ send_expect_100_continue(
|
||||
static_assert(is_sync_stream<SyncStream>::value,
|
||||
"SyncStream requirements not met");
|
||||
|
||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||
static_assert(
|
||||
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||
"DynamicBuffer requirements not met");
|
||||
|
||||
// Insert or replace the Expect field
|
||||
@ -123,7 +124,8 @@ receive_expect_100_continue(
|
||||
static_assert(is_sync_stream<SyncStream>::value,
|
||||
"SyncStream requirements not met");
|
||||
|
||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||
static_assert(
|
||||
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||
"DynamicBuffer requirements not met");
|
||||
|
||||
// Declare a parser for a request with a string body
|
||||
@ -194,9 +196,6 @@ send_cgi_response(
|
||||
static_assert(is_sync_write_stream<SyncWriteStream>::value,
|
||||
"SyncWriteStream requirements not met");
|
||||
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
|
||||
// Set up the response. We use the buffer_body type,
|
||||
// allowing serialization to use manually provided buffers.
|
||||
response<buffer_body> res;
|
||||
@ -293,7 +292,8 @@ void do_server_head(
|
||||
{
|
||||
static_assert(is_sync_stream<SyncStream>::value,
|
||||
"SyncStream requirements not met");
|
||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||
static_assert(
|
||||
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||
"DynamicBuffer requirments not met");
|
||||
|
||||
// We deliver this payload for all GET requests
|
||||
@ -386,7 +386,8 @@ do_head_request(
|
||||
// Do some type checking to be a good citizen
|
||||
static_assert(is_sync_stream<SyncStream>::value,
|
||||
"SyncStream requirements not met");
|
||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||
static_assert(
|
||||
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||
"DynamicBuffer requirments not met");
|
||||
|
||||
// The interfaces we are using are low level and do not
|
||||
@ -589,10 +590,6 @@ public:
|
||||
void
|
||||
operator()(error_code& ec, ConstBufferSequence const& buffers) const
|
||||
{
|
||||
// These asio functions are needed to access a buffer's contents
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
|
||||
// Error codes must be cleared on success
|
||||
ec = {};
|
||||
|
||||
@ -600,15 +597,16 @@ public:
|
||||
std::size_t bytes_transferred = 0;
|
||||
|
||||
// Loop over the buffer sequence
|
||||
for(auto it = buffers.begin(); it != buffers.end(); ++ it)
|
||||
for(auto it = boost::asio::buffer_sequence_begin(buffers);
|
||||
it != boost::asio::buffer_sequence_end(buffers); ++it)
|
||||
{
|
||||
// This is the next buffer in the sequence
|
||||
boost::asio::const_buffer const buffer = *it;
|
||||
|
||||
// Write it to the std::ostream
|
||||
os_.write(
|
||||
buffer_cast<char const*>(buffer),
|
||||
buffer_size(buffer));
|
||||
reinterpret_cast<char const*>(buffer.data()),
|
||||
buffer.size());
|
||||
|
||||
// If the std::ostream fails, convert it to an error code
|
||||
if(os_.fail())
|
||||
@ -714,13 +712,12 @@ read_istream(
|
||||
if(is.rdbuf()->in_avail() > 0)
|
||||
{
|
||||
// Get a mutable buffer sequence for writing
|
||||
auto const mb = buffer.prepare(
|
||||
auto const b = buffer.prepare(
|
||||
static_cast<std::size_t>(is.rdbuf()->in_avail()));
|
||||
|
||||
// Now get everything we can from the istream
|
||||
buffer.commit(static_cast<std::size_t>(is.readsome(
|
||||
boost::asio::buffer_cast<char*>(mb),
|
||||
boost::asio::buffer_size(mb))));
|
||||
reinterpret_cast<char*>(b.data()), b.size())));
|
||||
}
|
||||
else if(buffer.size() == 0)
|
||||
{
|
||||
@ -729,12 +726,10 @@ read_istream(
|
||||
if(! is.eof())
|
||||
{
|
||||
// Get a mutable buffer sequence for writing
|
||||
auto const mb = buffer.prepare(1024);
|
||||
auto const b = buffer.prepare(1024);
|
||||
|
||||
// Try to get more from the istream. This might block.
|
||||
is.read(
|
||||
boost::asio::buffer_cast<char*>(mb),
|
||||
boost::asio::buffer_size(mb));
|
||||
is.read(reinterpret_cast<char*>(b.data()), b.size());
|
||||
|
||||
// If an error occurs on the istream then return it to the caller.
|
||||
if(is.fail() && ! is.eof())
|
||||
|
@ -23,7 +23,7 @@ auto
|
||||
async_echo(AsyncStream& stream, CompletionToken&& token)
|
||||
|
||||
//]
|
||||
-> boost::beast::async_return_type<CompletionToken, void(boost::beast::error_code)>;
|
||||
-> BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(boost::beast::error_code));
|
||||
|
||||
//[example_core_echo_op_2
|
||||
|
||||
@ -61,14 +61,14 @@ async_echo(AsyncStream& stream, CompletionToken&& token)
|
||||
Regardless of whether the asynchronous operation completes
|
||||
immediately or not, the handler will not be invoked from within
|
||||
this function. Invocation of the handler will be performed in a
|
||||
manner equivalent to using `boost::asio::io_service::post`.
|
||||
manner equivalent to using `boost::asio::io_context::post`.
|
||||
*/
|
||||
template<
|
||||
class AsyncStream,
|
||||
class CompletionToken>
|
||||
boost::beast::async_return_type< /*< The [link beast.ref.boost__beast__async_return_type `async_return_type`] customizes the return value based on the completion token >*/
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE( /*< `BOOST_ASIO_INITFN_RESULT_TYPE` customizes the return value based on the completion token >*/
|
||||
CompletionToken,
|
||||
void(boost::beast::error_code)> /*< This is the signature for the completion handler >*/
|
||||
void(boost::beast::error_code)) /*< This is the signature for the completion handler >*/
|
||||
async_echo(
|
||||
AsyncStream& stream,
|
||||
CompletionToken&& token);
|
||||
@ -95,11 +95,13 @@ class echo_op
|
||||
// The buffer used to hold the input and output data.
|
||||
//
|
||||
// We use a custom allocator for performance, this allows
|
||||
// the implementation of the io_service to make efficient
|
||||
// the implementation of the io_context to make efficient
|
||||
// re-use of memory allocated by composed operations during
|
||||
// a continuation.
|
||||
//
|
||||
boost::asio::basic_streambuf<boost::beast::handler_alloc<char, Handler>> buffer;
|
||||
boost::asio::basic_streambuf<typename std::allocator_traits<
|
||||
boost::asio::associated_allocator_t<Handler> >::
|
||||
template rebind_alloc<char> > buffer;
|
||||
|
||||
// handler_ptr requires that the first parameter to the
|
||||
// contained object constructor is a reference to the
|
||||
@ -108,7 +110,7 @@ class echo_op
|
||||
explicit state(Handler& handler, AsyncStream& stream_)
|
||||
: stream(stream_)
|
||||
, buffer((std::numeric_limits<std::size_t>::max)(),
|
||||
boost::beast::handler_alloc<char, Handler>{handler})
|
||||
boost::asio::get_associated_allocator(handler))
|
||||
{
|
||||
}
|
||||
};
|
||||
@ -116,14 +118,10 @@ class echo_op
|
||||
// The operation's data is kept in a cheap-to-copy smart
|
||||
// pointer container called `handler_ptr`. This efficiently
|
||||
// satisfies the CopyConstructible requirements of completion
|
||||
// handlers.
|
||||
// handlers with expensive-to-copy state.
|
||||
//
|
||||
// `handler_ptr` uses these memory allocation hooks associated
|
||||
// with the final completion handler, in order to allocate the
|
||||
// storage for `state`:
|
||||
//
|
||||
// asio_handler_allocate
|
||||
// asio_handler_deallocate
|
||||
// `handler_ptr` uses the allocator associated with the final
|
||||
// completion handler, in order to allocate the storage for `state`.
|
||||
//
|
||||
boost::beast::handler_ptr<state, Handler> p_;
|
||||
|
||||
@ -144,30 +142,45 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
// Associated allocator support. This is Asio's system for
|
||||
// allowing the final completion handler to customize the
|
||||
// memory allocation strategy used for composed operation
|
||||
// states. A composed operation needs to use the same allocator
|
||||
// as the final handler. These declarations achieve that.
|
||||
|
||||
using allocator_type =
|
||||
boost::asio::associated_allocator_t<Handler>;
|
||||
|
||||
allocator_type
|
||||
get_allocator() const noexcept
|
||||
{
|
||||
return boost::asio::get_associated_allocator(p_.handler());
|
||||
}
|
||||
|
||||
// Executor hook. This is Asio's system for customizing the
|
||||
// manner in which asynchronous completion handlers are invoked.
|
||||
// A composed operation needs to use the same executor to invoke
|
||||
// intermediate completion handlers as that used to invoke the
|
||||
// final handler.
|
||||
|
||||
using executor_type = boost::asio::associated_executor_t<
|
||||
Handler, decltype(p_->stream.get_executor())>;
|
||||
|
||||
executor_type get_executor() const noexcept
|
||||
{
|
||||
return boost::asio::get_associated_executor(
|
||||
p_.handler(), p_->stream.get_executor());
|
||||
}
|
||||
|
||||
// (DEPRECATED)
|
||||
template<class AsyncStream_, class Handler_>
|
||||
friend bool asio_handler_is_continuation(
|
||||
echo_op<AsyncStream_, Handler_>* op);
|
||||
|
||||
// The entry point for this handler. This will get called
|
||||
// as our intermediate operations complete. Definition below.
|
||||
//
|
||||
void operator()(boost::beast::error_code ec, std::size_t bytes_transferred);
|
||||
|
||||
// The next four functions are required for our class
|
||||
// to meet the requirements for composed operations.
|
||||
// Definitions and exposition will follow.
|
||||
|
||||
template<class AsyncStream_, class Handler_, class Function>
|
||||
friend void asio_handler_invoke(
|
||||
Function&& f, echo_op<AsyncStream_, Handler_>* op);
|
||||
|
||||
template<class AsyncStream_, class Handler_>
|
||||
friend void* asio_handler_allocate(
|
||||
std::size_t size, echo_op<AsyncStream_, Handler_>* op);
|
||||
|
||||
template<class AsyncStream_, class Handler_>
|
||||
friend void asio_handler_deallocate(
|
||||
void* p, std::size_t size, echo_op<AsyncStream_, Handler_>* op);
|
||||
|
||||
template<class AsyncStream_, class Handler_>
|
||||
friend bool asio_handler_is_continuation(
|
||||
echo_op<AsyncStream_, Handler_>* op);
|
||||
};
|
||||
|
||||
//]
|
||||
@ -226,44 +239,6 @@ operator()(boost::beast::error_code ec, std::size_t bytes_transferred)
|
||||
|
||||
//[example_core_echo_op_6
|
||||
|
||||
// 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 the call through to the hook
|
||||
// associated with the final handler. The "using" statements are
|
||||
// structured to permit argument dependent lookup. Always use
|
||||
// `std::addressof` or its equivalent to pass the pointer to the
|
||||
// handler, otherwise an unwanted overload of `operator&` may be
|
||||
// called instead.
|
||||
|
||||
template<class AsyncStream, class Handler, class Function>
|
||||
void asio_handler_invoke(
|
||||
Function&& f, echo_op<AsyncStream, Handler>* op)
|
||||
{
|
||||
using boost::asio::asio_handler_invoke;
|
||||
return asio_handler_invoke(f, std::addressof(op->p_.handler()));
|
||||
}
|
||||
|
||||
template<class AsyncStream, class Handler>
|
||||
void* asio_handler_allocate(
|
||||
std::size_t size, echo_op<AsyncStream, Handler>* op)
|
||||
{
|
||||
using boost::asio::asio_handler_allocate;
|
||||
return asio_handler_allocate(size, std::addressof(op->p_.handler()));
|
||||
}
|
||||
|
||||
template<class AsyncStream, class Handler>
|
||||
void asio_handler_deallocate(
|
||||
void* p, std::size_t size, echo_op<AsyncStream, Handler>* op)
|
||||
{
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
return asio_handler_deallocate(p, size,
|
||||
std::addressof(op->p_.handler()));
|
||||
}
|
||||
|
||||
// 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
|
||||
@ -297,7 +272,7 @@ class echo_op;
|
||||
// Read a line and echo it back
|
||||
//
|
||||
template<class AsyncStream, class CompletionToken>
|
||||
boost::beast::async_return_type<CompletionToken, void(boost::beast::error_code)>
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(boost::beast::error_code))
|
||||
async_echo(AsyncStream& stream, CompletionToken&& token)
|
||||
{
|
||||
// Make sure stream meets the requirements. We use static_assert
|
||||
@ -310,16 +285,20 @@ async_echo(AsyncStream& stream, CompletionToken&& token)
|
||||
// uses the result and handler specializations associated with
|
||||
// the completion token to help customize the return value.
|
||||
//
|
||||
boost::beast::async_completion<CompletionToken, void(boost::beast::error_code)> init{token};
|
||||
boost::asio::async_completion<CompletionToken, void(boost::beast::error_code)> init{token};
|
||||
|
||||
// Create the composed operation and launch it. This is a constructor
|
||||
// call followed by invocation of operator(). We use handler_type
|
||||
// call followed by invocation of operator(). We use BOOST_ASIO_HANDLER_TYPE
|
||||
// to convert the completion token into the correct handler type,
|
||||
// allowing user-defined specializations of the async_result template
|
||||
// to be used.
|
||||
//
|
||||
echo_op<AsyncStream, boost::beast::handler_type<CompletionToken, void(boost::beast::error_code)>>{
|
||||
stream, init.completion_handler}(boost::beast::error_code{}, 0);
|
||||
echo_op<
|
||||
AsyncStream,
|
||||
BOOST_ASIO_HANDLER_TYPE(
|
||||
CompletionToken, void(boost::beast::error_code))>{
|
||||
stream,
|
||||
init.completion_handler}(boost::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
|
||||
@ -333,16 +312,15 @@ async_echo(AsyncStream& stream, CompletionToken&& token)
|
||||
|
||||
int main(int, char** argv)
|
||||
{
|
||||
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};
|
||||
boost::asio::io_context ioc;
|
||||
socket_type sock{ioc};
|
||||
boost::asio::ip::tcp::acceptor acceptor{ioc};
|
||||
endpoint_type ep{boost::asio::ip::make_address("0.0.0.0"), 0};
|
||||
acceptor.open(ep.protocol());
|
||||
acceptor.bind(ep);
|
||||
acceptor.listen();
|
||||
@ -353,6 +331,6 @@ int main(int, char** argv)
|
||||
if(ec)
|
||||
std::cerr << argv[0] << ": " << ec.message() << std::endl;
|
||||
});
|
||||
ios.run();
|
||||
ioc.run();
|
||||
return 0;
|
||||
}
|
||||
|
@ -50,11 +50,11 @@ class session : public std::enable_shared_from_this<session>
|
||||
http::response<http::string_body> res_;
|
||||
|
||||
public:
|
||||
// Resolver and stream require an io_service
|
||||
// Resolver and stream require an io_context
|
||||
explicit
|
||||
session(boost::asio::io_service& ios, ssl::context& ctx)
|
||||
: resolver_(ios)
|
||||
, stream_(ios, ctx)
|
||||
session(boost::asio::io_context& ioc, ssl::context& ctx)
|
||||
: resolver_(ioc)
|
||||
, stream_(ioc, ctx)
|
||||
{
|
||||
}
|
||||
|
||||
@ -73,7 +73,9 @@ public:
|
||||
req_.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
|
||||
|
||||
// Look up the domain name
|
||||
resolver_.async_resolve({host, port},
|
||||
resolver_.async_resolve(
|
||||
host,
|
||||
port,
|
||||
std::bind(
|
||||
&session::on_resolve,
|
||||
shared_from_this(),
|
||||
@ -84,7 +86,7 @@ public:
|
||||
void
|
||||
on_resolve(
|
||||
boost::system::error_code ec,
|
||||
tcp::resolver::iterator result)
|
||||
tcp::resolver::results_type results)
|
||||
{
|
||||
if(ec)
|
||||
return fail(ec, "resolve");
|
||||
@ -92,7 +94,8 @@ public:
|
||||
// Make the connection on the IP address we get from a lookup
|
||||
boost::asio::async_connect(
|
||||
stream_.next_layer(),
|
||||
result,
|
||||
results.begin(),
|
||||
results.end(),
|
||||
std::bind(
|
||||
&session::on_connect,
|
||||
shared_from_this(),
|
||||
@ -202,8 +205,8 @@ int main(int argc, char** argv)
|
||||
auto const port = argv[2];
|
||||
auto const target = argv[3];
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios;
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc;
|
||||
|
||||
// The SSL context is required, and holds certificates
|
||||
ssl::context ctx{ssl::context::sslv23_client};
|
||||
@ -212,11 +215,11 @@ int main(int argc, char** argv)
|
||||
load_root_certificates(ctx);
|
||||
|
||||
// Launch the asynchronous operation
|
||||
std::make_shared<session>(ios, ctx)->run(host, port, target);
|
||||
std::make_shared<session>(ioc, ctx)->run(host, port, target);
|
||||
|
||||
// Run the I/O service. The call will return when
|
||||
// the get operation is complete.
|
||||
ios.run();
|
||||
ioc.run();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -46,11 +46,11 @@ class session : public std::enable_shared_from_this<session>
|
||||
http::response<http::string_body> res_;
|
||||
|
||||
public:
|
||||
// Resolver and socket require an io_service
|
||||
// Resolver and socket require an io_context
|
||||
explicit
|
||||
session(boost::asio::io_service& ios)
|
||||
: resolver_(ios)
|
||||
, socket_(ios)
|
||||
session(boost::asio::io_context& ioc)
|
||||
: resolver_(ioc)
|
||||
, socket_(ioc)
|
||||
{
|
||||
}
|
||||
|
||||
@ -69,7 +69,9 @@ public:
|
||||
req_.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
|
||||
|
||||
// Look up the domain name
|
||||
resolver_.async_resolve({host, port},
|
||||
resolver_.async_resolve(
|
||||
host,
|
||||
port,
|
||||
std::bind(
|
||||
&session::on_resolve,
|
||||
shared_from_this(),
|
||||
@ -80,13 +82,16 @@ public:
|
||||
void
|
||||
on_resolve(
|
||||
boost::system::error_code ec,
|
||||
tcp::resolver::iterator result)
|
||||
tcp::resolver::results_type results)
|
||||
{
|
||||
if(ec)
|
||||
return fail(ec, "resolve");
|
||||
|
||||
// Make the connection on the IP address we get from a lookup
|
||||
boost::asio::async_connect(socket_, result,
|
||||
boost::asio::async_connect(
|
||||
socket_,
|
||||
results.begin(),
|
||||
results.end(),
|
||||
std::bind(
|
||||
&session::on_connect,
|
||||
shared_from_this(),
|
||||
@ -168,15 +173,15 @@ int main(int argc, char** argv)
|
||||
auto const port = argv[2];
|
||||
auto const target = argv[3];
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios;
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc;
|
||||
|
||||
// Launch the asynchronous operation
|
||||
std::make_shared<session>(ios)->run(host, port, target);
|
||||
std::make_shared<session>(ioc)->run(host, port, target);
|
||||
|
||||
// Run the I/O service. The call will return when
|
||||
// the get operation is complete.
|
||||
ios.run();
|
||||
ioc.run();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -46,23 +46,23 @@ do_session(
|
||||
std::string const& host,
|
||||
std::string const& port,
|
||||
std::string const& target,
|
||||
boost::asio::io_service& ios,
|
||||
boost::asio::io_context& ioc,
|
||||
ssl::context& ctx,
|
||||
boost::asio::yield_context yield)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
|
||||
// These objects perform our I/O
|
||||
tcp::resolver resolver{ios};
|
||||
ssl::stream<tcp::socket> stream{ios, ctx};
|
||||
tcp::resolver resolver{ioc};
|
||||
ssl::stream<tcp::socket> stream{ioc, ctx};
|
||||
|
||||
// Look up the domain name
|
||||
auto const lookup = resolver.async_resolve({host, port}, yield[ec]);
|
||||
auto const results = resolver.async_resolve(host, port, yield[ec]);
|
||||
if(ec)
|
||||
return fail(ec, "resolve");
|
||||
|
||||
// Make the connection on the IP address we get from a lookup
|
||||
boost::asio::async_connect(stream.next_layer(), lookup, yield[ec]);
|
||||
boost::asio::async_connect(stream.next_layer(), results.begin(), results.end(), yield[ec]);
|
||||
if(ec)
|
||||
return fail(ec, "connect");
|
||||
|
||||
@ -126,8 +126,8 @@ int main(int argc, char** argv)
|
||||
auto const port = argv[2];
|
||||
auto const target = argv[3];
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios;
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc;
|
||||
|
||||
// The SSL context is required, and holds certificates
|
||||
ssl::context ctx{ssl::context::sslv23_client};
|
||||
@ -136,18 +136,18 @@ int main(int argc, char** argv)
|
||||
load_root_certificates(ctx);
|
||||
|
||||
// Launch the asynchronous operation
|
||||
boost::asio::spawn(ios, std::bind(
|
||||
boost::asio::spawn(ioc, std::bind(
|
||||
&do_session,
|
||||
std::string(host),
|
||||
std::string(port),
|
||||
std::string(target),
|
||||
std::ref(ios),
|
||||
std::ref(ioc),
|
||||
std::ref(ctx),
|
||||
std::placeholders::_1));
|
||||
|
||||
// Run the I/O service. The call will return when
|
||||
// the get operation is complete.
|
||||
ios.run();
|
||||
ioc.run();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -42,22 +42,22 @@ do_session(
|
||||
std::string const& host,
|
||||
std::string const& port,
|
||||
std::string const& target,
|
||||
boost::asio::io_service& ios,
|
||||
boost::asio::io_context& ioc,
|
||||
boost::asio::yield_context yield)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
|
||||
// These objects perform our I/O
|
||||
tcp::resolver resolver{ios};
|
||||
tcp::socket socket{ios};
|
||||
tcp::resolver resolver{ioc};
|
||||
tcp::socket socket{ioc};
|
||||
|
||||
// Look up the domain name
|
||||
auto const lookup = resolver.async_resolve({host, port}, yield[ec]);
|
||||
auto const results = resolver.async_resolve(host, port, yield[ec]);
|
||||
if(ec)
|
||||
return fail(ec, "resolve");
|
||||
|
||||
// Make the connection on the IP address we get from a lookup
|
||||
boost::asio::async_connect(socket, lookup, yield[ec]);
|
||||
boost::asio::async_connect(socket, results.begin(), results.end(), yield[ec]);
|
||||
if(ec)
|
||||
return fail(ec, "connect");
|
||||
|
||||
@ -114,21 +114,21 @@ int main(int argc, char** argv)
|
||||
auto const port = argv[2];
|
||||
auto const target = argv[3];
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios;
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc;
|
||||
|
||||
// Launch the asynchronous operation
|
||||
boost::asio::spawn(ios, std::bind(
|
||||
boost::asio::spawn(ioc, std::bind(
|
||||
&do_session,
|
||||
std::string(host),
|
||||
std::string(port),
|
||||
std::string(target),
|
||||
std::ref(ios),
|
||||
std::ref(ioc),
|
||||
std::placeholders::_1));
|
||||
|
||||
// Run the I/O service. The call will return when
|
||||
// the get operation is complete.
|
||||
ios.run();
|
||||
ioc.run();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -18,10 +18,11 @@
|
||||
#include <boost/beast/core.hpp>
|
||||
#include <boost/beast/http.hpp>
|
||||
#include <boost/beast/version.hpp>
|
||||
#include <boost/asio/bind_executor.hpp>
|
||||
#include <boost/asio/connect.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <cstdlib>
|
||||
@ -43,16 +44,17 @@ namespace chrono = std::chrono; // from <chrono>
|
||||
// This structure aggregates statistics on all the sites
|
||||
class crawl_report
|
||||
{
|
||||
boost::asio::io_service& ios_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::io_context& ioc_;
|
||||
boost::asio::strand<
|
||||
boost::asio::io_context::executor_type> strand_;
|
||||
std::atomic<std::size_t> index_;
|
||||
std::vector<char const*> const& hosts_;
|
||||
std::size_t count_ = 0;
|
||||
|
||||
public:
|
||||
crawl_report(boost::asio::io_service& ios)
|
||||
: ios_(ios)
|
||||
, strand_(ios_)
|
||||
crawl_report(boost::asio::io_context& ioc)
|
||||
: ioc_(ioc)
|
||||
, strand_(ioc_.get_executor())
|
||||
, index_(0)
|
||||
, hosts_(urls_large_data())
|
||||
{
|
||||
@ -64,18 +66,19 @@ public:
|
||||
void
|
||||
aggregate(F const& f)
|
||||
{
|
||||
ios_.post(strand_.wrap(
|
||||
[&, f]
|
||||
{
|
||||
f(*this);
|
||||
if(count_ % 100 == 0)
|
||||
boost::asio::post(
|
||||
strand_,
|
||||
[&, f]
|
||||
{
|
||||
std::cerr <<
|
||||
"Progress: " << count_ << " of " << hosts_.size() << "\n";
|
||||
//std::cerr << *this;
|
||||
}
|
||||
++count_;
|
||||
}));
|
||||
f(*this);
|
||||
if(count_ % 100 == 0)
|
||||
{
|
||||
std::cerr <<
|
||||
"Progress: " << count_ << " of " << hosts_.size() << "\n";
|
||||
//std::cerr << *this;
|
||||
}
|
||||
++count_;
|
||||
});
|
||||
}
|
||||
|
||||
// Returns the next host to check
|
||||
@ -148,7 +151,8 @@ class worker : public std::enable_shared_from_this<worker>
|
||||
tcp::resolver resolver_;
|
||||
tcp::socket socket_;
|
||||
boost::asio::steady_timer timer_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::strand<
|
||||
boost::asio::io_context::executor_type> strand_;
|
||||
boost::beast::flat_buffer buffer_; // (Must persist between reads)
|
||||
http::request<http::empty_body> req_;
|
||||
http::response<http::string_body> res_;
|
||||
@ -156,16 +160,16 @@ class worker : public std::enable_shared_from_this<worker>
|
||||
public:
|
||||
worker(worker&&) = default;
|
||||
|
||||
// Resolver and socket require an io_service
|
||||
// Resolver and socket require an io_context
|
||||
worker(
|
||||
crawl_report& report,
|
||||
boost::asio::io_service& ios)
|
||||
boost::asio::io_context& ioc)
|
||||
: report_(report)
|
||||
, resolver_(ios)
|
||||
, socket_(ios)
|
||||
, timer_(ios,
|
||||
, resolver_(ioc)
|
||||
, socket_(ioc)
|
||||
, timer_(ioc,
|
||||
(chrono::steady_clock::time_point::max)())
|
||||
, strand_(ios)
|
||||
, strand_(ioc.get_executor())
|
||||
{
|
||||
// Set up the common fields of the request
|
||||
req_.version(11);
|
||||
@ -200,7 +204,7 @@ public:
|
||||
}
|
||||
|
||||
// Verify that the timer really expired since the deadline may have moved.
|
||||
if(timer_.expires_at() <= chrono::steady_clock::now())
|
||||
if(timer_.expiry() <= chrono::steady_clock::now())
|
||||
{
|
||||
socket_.shutdown(tcp::socket::shutdown_both, ec);
|
||||
socket_.close(ec);
|
||||
@ -209,10 +213,12 @@ public:
|
||||
|
||||
// Wait on the timer
|
||||
timer_.async_wait(
|
||||
strand_.wrap(std::bind(
|
||||
&worker::on_timer,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&worker::on_timer,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -224,8 +230,7 @@ public:
|
||||
// nullptr means no more work
|
||||
if(! host)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
timer_.cancel(ec);
|
||||
timer_.cancel_one();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -233,23 +238,26 @@ public:
|
||||
req_.set(http::field::host, host);
|
||||
|
||||
// Set the timer
|
||||
timer_.expires_from_now(chrono::seconds(timeout));
|
||||
timer_.expires_after(chrono::seconds(timeout));
|
||||
|
||||
// Set up an HTTP GET request message
|
||||
// Look up the domain name
|
||||
resolver_.async_resolve(
|
||||
tcp::resolver::query{host, "http"},
|
||||
strand_.wrap(std::bind(
|
||||
&worker::on_resolve,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
host,
|
||||
"http",
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&worker::on_resolve,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
}
|
||||
|
||||
void
|
||||
on_resolve(
|
||||
boost::system::error_code ec,
|
||||
tcp::resolver::iterator result)
|
||||
tcp::resolver::results_type results)
|
||||
{
|
||||
if(ec)
|
||||
{
|
||||
@ -262,16 +270,19 @@ public:
|
||||
}
|
||||
|
||||
// Set the timer
|
||||
timer_.expires_from_now(chrono::seconds(timeout));
|
||||
timer_.expires_after(chrono::seconds(timeout));
|
||||
|
||||
// Make the connection on the IP address we get from a lookup
|
||||
boost::asio::async_connect(
|
||||
socket_,
|
||||
result,
|
||||
strand_.wrap(std::bind(
|
||||
&worker::on_connect,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
results.begin(),
|
||||
results.end(),
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&worker::on_connect,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -288,17 +299,19 @@ public:
|
||||
}
|
||||
|
||||
// Set the timer
|
||||
timer_.expires_from_now(chrono::seconds(timeout));
|
||||
timer_.expires_after(chrono::seconds(timeout));
|
||||
|
||||
// Send the HTTP request to the remote host
|
||||
http::async_write(
|
||||
socket_,
|
||||
req_,
|
||||
strand_.wrap(std::bind(
|
||||
&worker::on_write,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&worker::on_write,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -319,18 +332,20 @@ public:
|
||||
}
|
||||
|
||||
// Set the timer
|
||||
timer_.expires_from_now(chrono::seconds(timeout));
|
||||
timer_.expires_after(chrono::seconds(timeout));
|
||||
|
||||
// Receive the HTTP response
|
||||
http::async_read(
|
||||
socket_,
|
||||
buffer_,
|
||||
res_,
|
||||
strand_.wrap(std::bind(
|
||||
&worker::on_read,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&worker::on_read,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -400,41 +415,41 @@ int main(int argc, char* argv[])
|
||||
" http-crawl 100 1\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto const threads = std::max<std::size_t>(1, std::atoi(argv[1]));
|
||||
auto const threads = std::max<int>(1, std::atoi(argv[1]));
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios{1};
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc{1};
|
||||
|
||||
// The work keeps io_service::run from returning
|
||||
boost::optional<boost::asio::io_service::work> work{ios};
|
||||
// The work keeps io_context::run from returning
|
||||
auto work = boost::asio::make_work_guard(ioc);
|
||||
|
||||
// The report holds the aggregated statistics
|
||||
crawl_report report{ios};
|
||||
crawl_report report{ioc};
|
||||
|
||||
timer t;
|
||||
|
||||
// Create and launch the worker threads.
|
||||
std::vector<std::thread> workers;
|
||||
workers.reserve(threads + 1);
|
||||
for(std::size_t i = 0; i < threads; ++i)
|
||||
for(int i = 0; i < threads; ++i)
|
||||
workers.emplace_back(
|
||||
[&report]
|
||||
{
|
||||
// We use a separate io_service for each worker because
|
||||
// We use a separate io_context for each worker because
|
||||
// the asio resolver simulates asynchronous operation using
|
||||
// a dedicated worker thread per io_service, and we want to
|
||||
// a dedicated worker thread per io_context, and we want to
|
||||
// do a lot of name resolutions in parallel.
|
||||
boost::asio::io_service ios{1};
|
||||
std::make_shared<worker>(report, ios)->run();
|
||||
ios.run();
|
||||
boost::asio::io_context ioc{1};
|
||||
std::make_shared<worker>(report, ioc)->run();
|
||||
ioc.run();
|
||||
});
|
||||
|
||||
// Add another thread to run the main io_service which
|
||||
// Add another thread to run the main io_context which
|
||||
// is used to aggregate the statistics
|
||||
workers.emplace_back(
|
||||
[&ios]
|
||||
[&ioc]
|
||||
{
|
||||
ios.run();
|
||||
ioc.run();
|
||||
});
|
||||
|
||||
// Now block until all threads exit
|
||||
@ -442,11 +457,10 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
auto& thread = workers[i];
|
||||
|
||||
// If this is the last thread, destroy the
|
||||
// If this is the last thread, reset the
|
||||
// work object so that it can return from run.
|
||||
//if(&thread == &workers.back())
|
||||
if(i == workers.size() - 1)
|
||||
work = boost::none;
|
||||
work.reset();
|
||||
|
||||
// Wait for the thread to exit
|
||||
thread.join();
|
||||
|
@ -47,8 +47,8 @@ int main(int argc, char** argv)
|
||||
auto const port = argv[2];
|
||||
auto const target = argv[3];
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios;
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc;
|
||||
|
||||
// The SSL context is required, and holds certificates
|
||||
ssl::context ctx{ssl::context::sslv23_client};
|
||||
@ -57,14 +57,14 @@ int main(int argc, char** argv)
|
||||
load_root_certificates(ctx);
|
||||
|
||||
// These objects perform our I/O
|
||||
tcp::resolver resolver{ios};
|
||||
ssl::stream<tcp::socket> stream{ios, ctx};
|
||||
tcp::resolver resolver{ioc};
|
||||
ssl::stream<tcp::socket> stream{ioc, ctx};
|
||||
|
||||
// Look up the domain name
|
||||
auto const lookup = resolver.resolve({host, port});
|
||||
auto const results = resolver.resolve(host, port);
|
||||
|
||||
// Make the connection on the IP address we get from a lookup
|
||||
boost::asio::connect(stream.next_layer(), lookup);
|
||||
boost::asio::connect(stream.next_layer(), results.begin(), results.end());
|
||||
|
||||
// Perform the SSL handshake
|
||||
stream.handshake(ssl::stream_base::client);
|
||||
|
@ -45,18 +45,18 @@ int main(int argc, char** argv)
|
||||
auto const port = argv[2];
|
||||
auto const target = argv[3];
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios;
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc;
|
||||
|
||||
// These objects perform our I/O
|
||||
tcp::resolver resolver{ios};
|
||||
tcp::socket socket{ios};
|
||||
tcp::resolver resolver{ioc};
|
||||
tcp::socket socket{ioc};
|
||||
|
||||
// Look up the domain name
|
||||
auto const lookup = resolver.resolve({host, port});
|
||||
auto const results = resolver.resolve(host, port);
|
||||
|
||||
// Make the connection on the IP address we get from a lookup
|
||||
boost::asio::connect(socket, lookup);
|
||||
boost::asio::connect(socket, results.begin(), results.end());
|
||||
|
||||
// Set up an HTTP GET request message
|
||||
http::request<http::string_body> req{http::verb::get, target, 11};
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <boost/beast/core.hpp>
|
||||
#include <boost/beast/http.hpp>
|
||||
#include <boost/beast/version.hpp>
|
||||
#include <boost/asio/bind_executor.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/ssl/stream.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
@ -244,18 +245,21 @@ class session : public std::enable_shared_from_this<session>
|
||||
http::async_write(
|
||||
self_.stream_,
|
||||
*sp,
|
||||
self_.strand_.wrap(std::bind(
|
||||
&session::on_write,
|
||||
self_.shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2,
|
||||
! sp->keep_alive())));
|
||||
boost::asio::bind_executor(
|
||||
self_.strand_,
|
||||
std::bind(
|
||||
&session::on_write,
|
||||
self_.shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2,
|
||||
! sp->keep_alive())));
|
||||
}
|
||||
};
|
||||
|
||||
tcp::socket socket_;
|
||||
ssl::stream<tcp::socket&> stream_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::strand<
|
||||
boost::asio::io_context::executor_type> strand_;
|
||||
boost::beast::flat_buffer buffer_;
|
||||
std::string const& doc_root_;
|
||||
http::request<http::string_body> req_;
|
||||
@ -271,7 +275,7 @@ public:
|
||||
std::string const& doc_root)
|
||||
: socket_(std::move(socket))
|
||||
, stream_(socket_, ctx)
|
||||
, strand_(socket_.get_io_service())
|
||||
, strand_(socket_.get_executor())
|
||||
, doc_root_(doc_root)
|
||||
, lambda_(*this)
|
||||
{
|
||||
@ -284,10 +288,12 @@ public:
|
||||
// Perform the SSL handshake
|
||||
stream_.async_handshake(
|
||||
ssl::stream_base::server,
|
||||
strand_.wrap(std::bind(
|
||||
&session::on_handshake,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&session::on_handshake,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -304,11 +310,13 @@ public:
|
||||
{
|
||||
// Read a request
|
||||
http::async_read(stream_, buffer_, req_,
|
||||
strand_.wrap(std::bind(
|
||||
&session::on_read,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&session::on_read,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -359,10 +367,12 @@ public:
|
||||
{
|
||||
// Perform the SSL shutdown
|
||||
stream_.async_shutdown(
|
||||
strand_.wrap(std::bind(
|
||||
&session::on_shutdown,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&session::on_shutdown,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -387,13 +397,13 @@ class listener : public std::enable_shared_from_this<listener>
|
||||
|
||||
public:
|
||||
listener(
|
||||
boost::asio::io_service& ios,
|
||||
boost::asio::io_context& ioc,
|
||||
ssl::context& ctx,
|
||||
tcp::endpoint endpoint,
|
||||
std::string const& doc_root)
|
||||
: ctx_(ctx)
|
||||
, acceptor_(ios)
|
||||
, socket_(ios)
|
||||
, acceptor_(ioc)
|
||||
, socket_(ioc)
|
||||
, doc_root_(doc_root)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
@ -416,7 +426,7 @@ public:
|
||||
|
||||
// Start listening for connections
|
||||
acceptor_.listen(
|
||||
boost::asio::socket_base::max_connections, ec);
|
||||
boost::asio::socket_base::max_listen_connections, ec);
|
||||
if(ec)
|
||||
{
|
||||
fail(ec, "listen");
|
||||
@ -478,13 +488,13 @@ int main(int argc, char* argv[])
|
||||
" http-server-async-ssl 0.0.0.0 8080 . 1\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto const address = boost::asio::ip::address::from_string(argv[1]);
|
||||
auto const address = boost::asio::ip::make_address(argv[1]);
|
||||
auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||
std::string const doc_root = argv[3];
|
||||
auto const threads = std::max<std::size_t>(1, std::atoi(argv[4]));
|
||||
auto const threads = std::max<int>(1, std::atoi(argv[4]));
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios{threads};
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc{threads};
|
||||
|
||||
// The SSL context is required, and holds certificates
|
||||
ssl::context ctx{ssl::context::sslv23};
|
||||
@ -494,7 +504,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
// Create and launch a listening port
|
||||
std::make_shared<listener>(
|
||||
ios,
|
||||
ioc,
|
||||
ctx,
|
||||
tcp::endpoint{address, port},
|
||||
doc_root)->run();
|
||||
@ -504,11 +514,11 @@ int main(int argc, char* argv[])
|
||||
v.reserve(threads - 1);
|
||||
for(auto i = threads - 1; i > 0; --i)
|
||||
v.emplace_back(
|
||||
[&ios]
|
||||
[&ioc]
|
||||
{
|
||||
ios.run();
|
||||
ioc.run();
|
||||
});
|
||||
ios.run();
|
||||
ioc.run();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <boost/beast/core.hpp>
|
||||
#include <boost/beast/http.hpp>
|
||||
#include <boost/beast/version.hpp>
|
||||
#include <boost/asio/bind_executor.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <boost/config.hpp>
|
||||
@ -240,17 +241,20 @@ class session : public std::enable_shared_from_this<session>
|
||||
http::async_write(
|
||||
self_.socket_,
|
||||
*sp,
|
||||
self_.strand_.wrap(std::bind(
|
||||
&session::on_write,
|
||||
self_.shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2,
|
||||
! sp->keep_alive())));
|
||||
boost::asio::bind_executor(
|
||||
self_.strand_,
|
||||
std::bind(
|
||||
&session::on_write,
|
||||
self_.shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2,
|
||||
! sp->keep_alive())));
|
||||
}
|
||||
};
|
||||
|
||||
tcp::socket socket_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::strand<
|
||||
boost::asio::io_context::executor_type> strand_;
|
||||
boost::beast::flat_buffer buffer_;
|
||||
std::string const& doc_root_;
|
||||
http::request<http::string_body> req_;
|
||||
@ -264,7 +268,7 @@ public:
|
||||
tcp::socket socket,
|
||||
std::string const& doc_root)
|
||||
: socket_(std::move(socket))
|
||||
, strand_(socket_.get_io_service())
|
||||
, strand_(socket_.get_executor())
|
||||
, doc_root_(doc_root)
|
||||
, lambda_(*this)
|
||||
{
|
||||
@ -282,11 +286,13 @@ public:
|
||||
{
|
||||
// Read a request
|
||||
http::async_read(socket_, buffer_, req_,
|
||||
strand_.wrap(std::bind(
|
||||
&session::on_read,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&session::on_read,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -354,11 +360,11 @@ class listener : public std::enable_shared_from_this<listener>
|
||||
|
||||
public:
|
||||
listener(
|
||||
boost::asio::io_service& ios,
|
||||
boost::asio::io_context& ioc,
|
||||
tcp::endpoint endpoint,
|
||||
std::string const& doc_root)
|
||||
: acceptor_(ios)
|
||||
, socket_(ios)
|
||||
: acceptor_(ioc)
|
||||
, socket_(ioc)
|
||||
, doc_root_(doc_root)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
@ -381,7 +387,7 @@ public:
|
||||
|
||||
// Start listening for connections
|
||||
acceptor_.listen(
|
||||
boost::asio::socket_base::max_connections, ec);
|
||||
boost::asio::socket_base::max_listen_connections, ec);
|
||||
if(ec)
|
||||
{
|
||||
fail(ec, "listen");
|
||||
@ -442,17 +448,17 @@ int main(int argc, char* argv[])
|
||||
" http-server-async 0.0.0.0 8080 . 1\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto const address = boost::asio::ip::address::from_string(argv[1]);
|
||||
auto const address = boost::asio::ip::make_address(argv[1]);
|
||||
auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||
std::string const doc_root = argv[3];
|
||||
auto const threads = std::max<std::size_t>(1, std::atoi(argv[4]));
|
||||
auto const threads = std::max<int>(1, std::atoi(argv[4]));
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios{threads};
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc{threads};
|
||||
|
||||
// Create and launch a listening port
|
||||
std::make_shared<listener>(
|
||||
ios,
|
||||
ioc,
|
||||
tcp::endpoint{address, port},
|
||||
doc_root)->run();
|
||||
|
||||
@ -461,11 +467,11 @@ int main(int argc, char* argv[])
|
||||
v.reserve(threads - 1);
|
||||
for(auto i = threads - 1; i > 0; --i)
|
||||
v.emplace_back(
|
||||
[&ios]
|
||||
[&ioc]
|
||||
{
|
||||
ios.run();
|
||||
ioc.run();
|
||||
});
|
||||
ios.run();
|
||||
ioc.run();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -308,7 +308,7 @@ do_session(
|
||||
// Accepts incoming connections and launches the sessions
|
||||
void
|
||||
do_listen(
|
||||
boost::asio::io_service& ios,
|
||||
boost::asio::io_context& ioc,
|
||||
ssl::context& ctx,
|
||||
tcp::endpoint endpoint,
|
||||
std::string const& doc_root,
|
||||
@ -317,7 +317,7 @@ do_listen(
|
||||
boost::system::error_code ec;
|
||||
|
||||
// Open the acceptor
|
||||
tcp::acceptor acceptor(ios);
|
||||
tcp::acceptor acceptor(ioc);
|
||||
acceptor.open(endpoint.protocol(), ec);
|
||||
if(ec)
|
||||
return fail(ec, "open");
|
||||
@ -328,19 +328,19 @@ do_listen(
|
||||
return fail(ec, "bind");
|
||||
|
||||
// Start listening for connections
|
||||
acceptor.listen(boost::asio::socket_base::max_connections, ec);
|
||||
acceptor.listen(boost::asio::socket_base::max_listen_connections, ec);
|
||||
if(ec)
|
||||
return fail(ec, "listen");
|
||||
|
||||
for(;;)
|
||||
{
|
||||
tcp::socket socket(ios);
|
||||
tcp::socket socket(ioc);
|
||||
acceptor.async_accept(socket, yield[ec]);
|
||||
if(ec)
|
||||
fail(ec, "accept");
|
||||
else
|
||||
boost::asio::spawn(
|
||||
acceptor.get_io_service(),
|
||||
acceptor.get_executor().context(),
|
||||
std::bind(
|
||||
&do_session,
|
||||
std::move(socket),
|
||||
@ -361,13 +361,13 @@ int main(int argc, char* argv[])
|
||||
" http-server-coro-ssl 0.0.0.0 8080 . 1\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto const address = boost::asio::ip::address::from_string(argv[1]);
|
||||
auto const address = boost::asio::ip::make_address(argv[1]);
|
||||
auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||
std::string const doc_root = argv[3];
|
||||
auto const threads = std::max<std::size_t>(1, std::atoi(argv[4]));
|
||||
auto const threads = std::max<int>(1, std::atoi(argv[4]));
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios{threads};
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc{threads};
|
||||
|
||||
// The SSL context is required, and holds certificates
|
||||
ssl::context ctx{ssl::context::sslv23};
|
||||
@ -376,10 +376,10 @@ int main(int argc, char* argv[])
|
||||
load_server_certificate(ctx);
|
||||
|
||||
// Spawn a listening port
|
||||
boost::asio::spawn(ios,
|
||||
boost::asio::spawn(ioc,
|
||||
std::bind(
|
||||
&do_listen,
|
||||
std::ref(ios),
|
||||
std::ref(ioc),
|
||||
std::ref(ctx),
|
||||
tcp::endpoint{address, port},
|
||||
doc_root,
|
||||
@ -390,11 +390,11 @@ int main(int argc, char* argv[])
|
||||
v.reserve(threads - 1);
|
||||
for(auto i = threads - 1; i > 0; --i)
|
||||
v.emplace_back(
|
||||
[&ios]
|
||||
[&ioc]
|
||||
{
|
||||
ios.run();
|
||||
ioc.run();
|
||||
});
|
||||
ios.run();
|
||||
ioc.run();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -293,7 +293,7 @@ do_session(
|
||||
// Accepts incoming connections and launches the sessions
|
||||
void
|
||||
do_listen(
|
||||
boost::asio::io_service& ios,
|
||||
boost::asio::io_context& ioc,
|
||||
tcp::endpoint endpoint,
|
||||
std::string const& doc_root,
|
||||
boost::asio::yield_context yield)
|
||||
@ -301,7 +301,7 @@ do_listen(
|
||||
boost::system::error_code ec;
|
||||
|
||||
// Open the acceptor
|
||||
tcp::acceptor acceptor(ios);
|
||||
tcp::acceptor acceptor(ioc);
|
||||
acceptor.open(endpoint.protocol(), ec);
|
||||
if(ec)
|
||||
return fail(ec, "open");
|
||||
@ -312,19 +312,19 @@ do_listen(
|
||||
return fail(ec, "bind");
|
||||
|
||||
// Start listening for connections
|
||||
acceptor.listen(boost::asio::socket_base::max_connections, ec);
|
||||
acceptor.listen(boost::asio::socket_base::max_listen_connections, ec);
|
||||
if(ec)
|
||||
return fail(ec, "listen");
|
||||
|
||||
for(;;)
|
||||
{
|
||||
tcp::socket socket(ios);
|
||||
tcp::socket socket(ioc);
|
||||
acceptor.async_accept(socket, yield[ec]);
|
||||
if(ec)
|
||||
fail(ec, "accept");
|
||||
else
|
||||
boost::asio::spawn(
|
||||
acceptor.get_io_service(),
|
||||
acceptor.get_executor().context(),
|
||||
std::bind(
|
||||
&do_session,
|
||||
std::move(socket),
|
||||
@ -344,19 +344,19 @@ int main(int argc, char* argv[])
|
||||
" http-server-coro 0.0.0.0 8080 . 1\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto const address = boost::asio::ip::address::from_string(argv[1]);
|
||||
auto const address = boost::asio::ip::make_address(argv[1]);
|
||||
auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||
std::string const doc_root = argv[3];
|
||||
auto const threads = std::max<std::size_t>(1, std::atoi(argv[4]));
|
||||
auto const threads = std::max<int>(1, std::atoi(argv[4]));
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios{threads};
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc{threads};
|
||||
|
||||
// Spawn a listening port
|
||||
boost::asio::spawn(ios,
|
||||
boost::asio::spawn(ioc,
|
||||
std::bind(
|
||||
&do_listen,
|
||||
std::ref(ios),
|
||||
std::ref(ioc),
|
||||
tcp::endpoint{address, port},
|
||||
doc_root,
|
||||
std::placeholders::_1));
|
||||
@ -366,11 +366,11 @@ int main(int argc, char* argv[])
|
||||
v.reserve(threads - 1);
|
||||
for(auto i = threads - 1; i > 0; --i)
|
||||
v.emplace_back(
|
||||
[&ios]
|
||||
[&ioc]
|
||||
{
|
||||
ios.run();
|
||||
ioc.run();
|
||||
});
|
||||
ios.run();
|
||||
ioc.run();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ private:
|
||||
std::string doc_root_;
|
||||
|
||||
// The socket for the currently connected client.
|
||||
tcp::socket socket_{acceptor_.get_io_service()};
|
||||
tcp::socket socket_{acceptor_.get_executor().context()};
|
||||
|
||||
// The buffer for performing reads
|
||||
boost::beast::flat_static_buffer<8192> buffer_;
|
||||
@ -110,7 +110,7 @@ private:
|
||||
|
||||
// The timer putting a time limit on requests.
|
||||
boost::asio::basic_waitable_timer<std::chrono::steady_clock> request_deadline_{
|
||||
acceptor_.get_io_service(), (std::chrono::steady_clock::time_point::max)()};
|
||||
acceptor_.get_executor().context(), (std::chrono::steady_clock::time_point::max)()};
|
||||
|
||||
// The string-based response message.
|
||||
boost::optional<http::response<http::string_body, http::basic_fields<alloc_t>>> string_response_;
|
||||
@ -142,7 +142,7 @@ private:
|
||||
else
|
||||
{
|
||||
// Request must be fully processed within 60 seconds.
|
||||
request_deadline_.expires_from_now(
|
||||
request_deadline_.expires_after(
|
||||
std::chrono::seconds(60));
|
||||
|
||||
read_request();
|
||||
@ -288,7 +288,7 @@ private:
|
||||
void check_deadline()
|
||||
{
|
||||
// The deadline may have moved, so check it has really passed.
|
||||
if (request_deadline_.expires_at() <= std::chrono::steady_clock::now())
|
||||
if (request_deadline_.expiry() <= std::chrono::steady_clock::now())
|
||||
{
|
||||
// Close socket to cancel any outstanding operation.
|
||||
boost::beast::error_code ec;
|
||||
@ -322,14 +322,14 @@ int main(int argc, char* argv[])
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
auto address = ip::address::from_string(argv[1]);
|
||||
auto const address = boost::asio::ip::make_address(argv[1]);
|
||||
unsigned short port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||
std::string doc_root = argv[3];
|
||||
int num_workers = std::atoi(argv[4]);
|
||||
bool spin = (std::strcmp(argv[5], "spin") == 0);
|
||||
|
||||
boost::asio::io_service ios{1};
|
||||
tcp::acceptor acceptor{ios, {address, port}};
|
||||
boost::asio::io_context ioc{1};
|
||||
tcp::acceptor acceptor{ioc, {address, port}};
|
||||
|
||||
std::list<http_worker> workers;
|
||||
for (int i = 0; i < num_workers; ++i)
|
||||
@ -339,9 +339,9 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
|
||||
if (spin)
|
||||
for (;;) ios.poll();
|
||||
for (;;) ioc.poll();
|
||||
else
|
||||
ios.run();
|
||||
ioc.run();
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <boost/beast/core.hpp>
|
||||
#include <boost/beast/http.hpp>
|
||||
#include <boost/beast/version.hpp>
|
||||
#include <boost/asio/bind_executor.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/ssl/stream.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
@ -255,12 +256,14 @@ class session
|
||||
http::async_write(
|
||||
self_.derived().stream(),
|
||||
*sp,
|
||||
self_.strand_.wrap(std::bind(
|
||||
&session::on_write,
|
||||
self_.derived().shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2,
|
||||
! sp->keep_alive())));
|
||||
boost::asio::bind_executor(
|
||||
self_.strand_,
|
||||
std::bind(
|
||||
&session::on_write,
|
||||
self_.derived().shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2,
|
||||
! sp->keep_alive())));
|
||||
}
|
||||
};
|
||||
|
||||
@ -270,19 +273,20 @@ class session
|
||||
send_lambda lambda_;
|
||||
|
||||
protected:
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::strand<
|
||||
boost::asio::io_context::executor_type> strand_;
|
||||
boost::beast::flat_buffer buffer_;
|
||||
|
||||
public:
|
||||
// Take ownership of the buffer
|
||||
explicit
|
||||
session(
|
||||
boost::asio::io_service& ios,
|
||||
boost::asio::io_context& ioc,
|
||||
boost::beast::flat_buffer buffer,
|
||||
std::string const& doc_root)
|
||||
: doc_root_(doc_root)
|
||||
, lambda_(*this)
|
||||
, strand_(ios)
|
||||
, strand_(ioc.get_executor())
|
||||
, buffer_(std::move(buffer))
|
||||
{
|
||||
}
|
||||
@ -295,11 +299,13 @@ public:
|
||||
derived().stream(),
|
||||
buffer_,
|
||||
req_,
|
||||
strand_.wrap(std::bind(
|
||||
&session::on_read,
|
||||
derived().shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&session::on_read,
|
||||
derived().shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -352,7 +358,8 @@ class plain_session
|
||||
, public std::enable_shared_from_this<plain_session>
|
||||
{
|
||||
tcp::socket socket_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::strand<
|
||||
boost::asio::io_context::executor_type> strand_;
|
||||
|
||||
public:
|
||||
// Create the session
|
||||
@ -361,11 +368,11 @@ public:
|
||||
boost::beast::flat_buffer buffer,
|
||||
std::string const& doc_root)
|
||||
: session<plain_session>(
|
||||
socket.get_io_service(),
|
||||
socket.get_executor().context(),
|
||||
std::move(buffer),
|
||||
doc_root)
|
||||
, socket_(std::move(socket))
|
||||
, strand_(socket_.get_io_service())
|
||||
, strand_(socket_.get_executor())
|
||||
{
|
||||
}
|
||||
|
||||
@ -401,7 +408,8 @@ class ssl_session
|
||||
{
|
||||
tcp::socket socket_;
|
||||
ssl::stream<tcp::socket&> stream_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::strand<
|
||||
boost::asio::io_context::executor_type> strand_;
|
||||
|
||||
public:
|
||||
// Create the session
|
||||
@ -411,12 +419,12 @@ public:
|
||||
boost::beast::flat_buffer buffer,
|
||||
std::string const& doc_root)
|
||||
: session<ssl_session>(
|
||||
socket.get_io_service(),
|
||||
socket.get_executor().context(),
|
||||
std::move(buffer),
|
||||
doc_root)
|
||||
, socket_(std::move(socket))
|
||||
, stream_(socket_, ctx)
|
||||
, strand_(stream_.get_io_service())
|
||||
, strand_(stream_.get_executor())
|
||||
{
|
||||
}
|
||||
|
||||
@ -436,11 +444,13 @@ public:
|
||||
stream_.async_handshake(
|
||||
ssl::stream_base::server,
|
||||
buffer_.data(),
|
||||
strand_.wrap(std::bind(
|
||||
&ssl_session::on_handshake,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&ssl_session::on_handshake,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
}
|
||||
void
|
||||
on_handshake(
|
||||
@ -461,10 +471,12 @@ public:
|
||||
{
|
||||
// Perform the SSL shutdown
|
||||
stream_.async_shutdown(
|
||||
strand_.wrap(std::bind(
|
||||
&ssl_session::on_shutdown,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&ssl_session::on_shutdown,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -484,7 +496,8 @@ class detect_session : public std::enable_shared_from_this<detect_session>
|
||||
{
|
||||
tcp::socket socket_;
|
||||
ssl::context& ctx_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::strand<
|
||||
boost::asio::io_context::executor_type> strand_;
|
||||
std::string const& doc_root_;
|
||||
boost::beast::flat_buffer buffer_;
|
||||
|
||||
@ -496,7 +509,7 @@ public:
|
||||
std::string const& doc_root)
|
||||
: socket_(std::move(socket))
|
||||
, ctx_(ctx)
|
||||
, strand_(socket_.get_io_service())
|
||||
, strand_(socket_.get_executor())
|
||||
, doc_root_(doc_root)
|
||||
{
|
||||
}
|
||||
@ -508,11 +521,13 @@ public:
|
||||
async_detect_ssl(
|
||||
socket_,
|
||||
buffer_,
|
||||
strand_.wrap(std::bind(
|
||||
&detect_session::on_detect,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&detect_session::on_detect,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
|
||||
}
|
||||
|
||||
@ -545,21 +560,22 @@ public:
|
||||
class listener : public std::enable_shared_from_this<listener>
|
||||
{
|
||||
ssl::context& ctx_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::strand<
|
||||
boost::asio::io_context::executor_type> strand_;
|
||||
tcp::acceptor acceptor_;
|
||||
tcp::socket socket_;
|
||||
std::string const& doc_root_;
|
||||
|
||||
public:
|
||||
listener(
|
||||
boost::asio::io_service& ios,
|
||||
boost::asio::io_context& ioc,
|
||||
ssl::context& ctx,
|
||||
tcp::endpoint endpoint,
|
||||
std::string const& doc_root)
|
||||
: ctx_(ctx)
|
||||
, strand_(ios)
|
||||
, acceptor_(ios)
|
||||
, socket_(ios)
|
||||
, strand_(ioc.get_executor())
|
||||
, acceptor_(ioc)
|
||||
, socket_(ioc)
|
||||
, doc_root_(doc_root)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
@ -582,7 +598,7 @@ public:
|
||||
|
||||
// Start listening for connections
|
||||
acceptor_.listen(
|
||||
boost::asio::socket_base::max_connections, ec);
|
||||
boost::asio::socket_base::max_listen_connections, ec);
|
||||
if(ec)
|
||||
{
|
||||
fail(ec, "listen");
|
||||
@ -644,13 +660,13 @@ int main(int argc, char* argv[])
|
||||
" http-server-sync 0.0.0.0 8080 .\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto const address = boost::asio::ip::address::from_string(argv[1]);
|
||||
auto const address = boost::asio::ip::make_address(argv[1]);
|
||||
auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||
std::string const doc_root = argv[3];
|
||||
auto const threads = std::max<std::size_t>(1, std::atoi(argv[4]));
|
||||
auto const threads = std::max<int>(1, std::atoi(argv[4]));
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios{threads};
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc{threads};
|
||||
|
||||
// The SSL context is required, and holds certificates
|
||||
ssl::context ctx{ssl::context::sslv23};
|
||||
@ -660,7 +676,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
// Create and launch a listening port
|
||||
std::make_shared<listener>(
|
||||
ios,
|
||||
ioc,
|
||||
ctx,
|
||||
tcp::endpoint{address, port},
|
||||
doc_root)->run();
|
||||
@ -670,11 +686,11 @@ int main(int argc, char* argv[])
|
||||
v.reserve(threads - 1);
|
||||
for(auto i = threads - 1; i > 0; --i)
|
||||
v.emplace_back(
|
||||
[&ios]
|
||||
[&ioc]
|
||||
{
|
||||
ios.run();
|
||||
ioc.run();
|
||||
});
|
||||
ios.run();
|
||||
ioc.run();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ private:
|
||||
|
||||
// The timer for putting a deadline on connection processing.
|
||||
boost::asio::basic_waitable_timer<std::chrono::steady_clock> deadline_{
|
||||
socket_.get_io_service(), std::chrono::seconds(60)};
|
||||
socket_.get_executor().context(), std::chrono::seconds(60)};
|
||||
|
||||
// Asynchronously receive a complete request message.
|
||||
void
|
||||
@ -231,16 +231,16 @@ main(int argc, char* argv[])
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
auto address = ip::address::from_string(argv[1]);
|
||||
auto const address = boost::asio::ip::make_address(argv[1]);
|
||||
unsigned short port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||
|
||||
boost::asio::io_service ios{1};
|
||||
boost::asio::io_context ioc{1};
|
||||
|
||||
tcp::acceptor acceptor{ios, {address, port}};
|
||||
tcp::socket socket{ios};
|
||||
tcp::acceptor acceptor{ioc, {address, port}};
|
||||
tcp::socket socket{ioc};
|
||||
http_server(acceptor, socket);
|
||||
|
||||
ios.run();
|
||||
ioc.run();
|
||||
}
|
||||
catch(std::exception const& e)
|
||||
{
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <boost/beast/core.hpp>
|
||||
#include <boost/beast/http.hpp>
|
||||
#include <boost/beast/version.hpp>
|
||||
#include <boost/asio/bind_executor.hpp>
|
||||
#include <boost/asio/coroutine.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/ssl/stream.hpp>
|
||||
@ -247,18 +248,21 @@ class session
|
||||
http::async_write(
|
||||
self_.socket_,
|
||||
*sp,
|
||||
self_.strand_.wrap(std::bind(
|
||||
&session::loop,
|
||||
self_.shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2,
|
||||
! sp->keep_alive())));
|
||||
boost::asio::bind_executor(
|
||||
self_.strand_,
|
||||
std::bind(
|
||||
&session::loop,
|
||||
self_.shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2,
|
||||
! sp->keep_alive())));
|
||||
}
|
||||
};
|
||||
|
||||
tcp::socket socket_;
|
||||
ssl::stream<tcp::socket&> stream_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::strand<
|
||||
boost::asio::io_context::executor_type> strand_;
|
||||
boost::beast::flat_buffer buffer_;
|
||||
std::string const& doc_root_;
|
||||
http::request<http::string_body> req_;
|
||||
@ -274,7 +278,7 @@ public:
|
||||
std::string const& doc_root)
|
||||
: socket_(std::move(socket))
|
||||
, stream_(socket_, ctx)
|
||||
, strand_(socket_.get_io_service())
|
||||
, strand_(socket_.get_executor())
|
||||
, doc_root_(doc_root)
|
||||
, lambda_(*this)
|
||||
{
|
||||
@ -300,12 +304,14 @@ public:
|
||||
// Perform the SSL handshake
|
||||
yield stream_.async_handshake(
|
||||
ssl::stream_base::server,
|
||||
strand_.wrap(std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
0,
|
||||
false)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
0,
|
||||
false)));
|
||||
if(ec)
|
||||
return fail(ec, "handshake");
|
||||
|
||||
@ -313,12 +319,14 @@ public:
|
||||
{
|
||||
// Read a request
|
||||
yield http::async_read(stream_, buffer_, req_,
|
||||
strand_.wrap(std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2,
|
||||
false)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2,
|
||||
false)));
|
||||
if(ec == http::error::end_of_stream)
|
||||
{
|
||||
// The remote host closed the connection
|
||||
@ -344,12 +352,14 @@ public:
|
||||
|
||||
// Perform the SSL shutdown
|
||||
yield stream_.async_shutdown(
|
||||
strand_.wrap(std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
0,
|
||||
false)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
0,
|
||||
false)));
|
||||
if(ec)
|
||||
return fail(ec, "shutdown");
|
||||
|
||||
@ -373,13 +383,13 @@ class listener
|
||||
|
||||
public:
|
||||
listener(
|
||||
boost::asio::io_service& ios,
|
||||
boost::asio::io_context& ioc,
|
||||
ssl::context& ctx,
|
||||
tcp::endpoint endpoint,
|
||||
std::string const& doc_root)
|
||||
: ctx_(ctx)
|
||||
, acceptor_(ios)
|
||||
, socket_(ios)
|
||||
, acceptor_(ioc)
|
||||
, socket_(ioc)
|
||||
, doc_root_(doc_root)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
@ -402,7 +412,7 @@ public:
|
||||
|
||||
// Start listening for connections
|
||||
acceptor_.listen(
|
||||
boost::asio::socket_base::max_connections, ec);
|
||||
boost::asio::socket_base::max_listen_connections, ec);
|
||||
if(ec)
|
||||
{
|
||||
fail(ec, "listen");
|
||||
@ -464,13 +474,13 @@ int main(int argc, char* argv[])
|
||||
" http-server-stackless-ssl 0.0.0.0 8080 . 1\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto const address = boost::asio::ip::address::from_string(argv[1]);
|
||||
auto const address = boost::asio::ip::make_address(argv[1]);
|
||||
auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||
std::string const doc_root = argv[3];
|
||||
auto const threads = std::max<std::size_t>(1, std::atoi(argv[4]));
|
||||
auto const threads = std::max<int>(1, std::atoi(argv[4]));
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios{threads};
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc{threads};
|
||||
|
||||
// The SSL context is required, and holds certificates
|
||||
ssl::context ctx{ssl::context::sslv23};
|
||||
@ -480,7 +490,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
// Create and launch a listening port
|
||||
std::make_shared<listener>(
|
||||
ios,
|
||||
ioc,
|
||||
ctx,
|
||||
tcp::endpoint{address, port},
|
||||
doc_root)->run();
|
||||
@ -490,11 +500,11 @@ int main(int argc, char* argv[])
|
||||
v.reserve(threads - 1);
|
||||
for(auto i = threads - 1; i > 0; --i)
|
||||
v.emplace_back(
|
||||
[&ios]
|
||||
[&ioc]
|
||||
{
|
||||
ios.run();
|
||||
ioc.run();
|
||||
});
|
||||
ios.run();
|
||||
ioc.run();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <boost/beast/core.hpp>
|
||||
#include <boost/beast/http.hpp>
|
||||
#include <boost/beast/version.hpp>
|
||||
#include <boost/asio/bind_executor.hpp>
|
||||
#include <boost/asio/coroutine.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
@ -244,17 +245,20 @@ class session
|
||||
http::async_write(
|
||||
self_.socket_,
|
||||
*sp,
|
||||
self_.strand_.wrap(std::bind(
|
||||
&session::loop,
|
||||
self_.shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2,
|
||||
! sp->keep_alive())));
|
||||
boost::asio::bind_executor(
|
||||
self_.strand_,
|
||||
std::bind(
|
||||
&session::loop,
|
||||
self_.shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2,
|
||||
! sp->keep_alive())));
|
||||
}
|
||||
};
|
||||
|
||||
tcp::socket socket_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::strand<
|
||||
boost::asio::io_context::executor_type> strand_;
|
||||
boost::beast::flat_buffer buffer_;
|
||||
std::string const& doc_root_;
|
||||
http::request<http::string_body> req_;
|
||||
@ -268,7 +272,7 @@ public:
|
||||
tcp::socket socket,
|
||||
std::string const& doc_root)
|
||||
: socket_(std::move(socket))
|
||||
, strand_(socket_.get_io_service())
|
||||
, strand_(socket_.get_executor())
|
||||
, doc_root_(doc_root)
|
||||
, lambda_(*this)
|
||||
{
|
||||
@ -295,12 +299,14 @@ public:
|
||||
{
|
||||
// Read a request
|
||||
yield http::async_read(socket_, buffer_, req_,
|
||||
strand_.wrap(std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2,
|
||||
false)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2,
|
||||
false)));
|
||||
if(ec == http::error::end_of_stream)
|
||||
{
|
||||
// The remote host closed the connection
|
||||
@ -346,11 +352,11 @@ class listener
|
||||
|
||||
public:
|
||||
listener(
|
||||
boost::asio::io_service& ios,
|
||||
boost::asio::io_context& ioc,
|
||||
tcp::endpoint endpoint,
|
||||
std::string const& doc_root)
|
||||
: acceptor_(ios)
|
||||
, socket_(ios)
|
||||
: acceptor_(ioc)
|
||||
, socket_(ioc)
|
||||
, doc_root_(doc_root)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
@ -372,7 +378,7 @@ public:
|
||||
}
|
||||
|
||||
// Start listening for connections
|
||||
acceptor_.listen(boost::asio::socket_base::max_connections, ec);
|
||||
acceptor_.listen(boost::asio::socket_base::max_listen_connections, ec);
|
||||
if(ec)
|
||||
{
|
||||
fail(ec, "listen");
|
||||
@ -433,17 +439,17 @@ int main(int argc, char* argv[])
|
||||
" http-server-stackless 0.0.0.0 8080 . 1\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto const address = boost::asio::ip::address::from_string(argv[1]);
|
||||
auto const address = boost::asio::ip::make_address(argv[1]);
|
||||
auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||
std::string const doc_root = argv[3];
|
||||
auto const threads = std::max<std::size_t>(1, std::atoi(argv[4]));
|
||||
auto const threads = std::max<int>(1, std::atoi(argv[4]));
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios{threads};
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc{threads};
|
||||
|
||||
// Create and launch a listening port
|
||||
std::make_shared<listener>(
|
||||
ios,
|
||||
ioc,
|
||||
tcp::endpoint{address, port},
|
||||
doc_root)->run();
|
||||
|
||||
@ -452,11 +458,11 @@ int main(int argc, char* argv[])
|
||||
v.reserve(threads - 1);
|
||||
for(auto i = threads - 1; i > 0; --i)
|
||||
v.emplace_back(
|
||||
[&ios]
|
||||
[&ioc]
|
||||
{
|
||||
ios.run();
|
||||
ioc.run();
|
||||
});
|
||||
ios.run();
|
||||
ioc.run();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -311,12 +311,12 @@ int main(int argc, char* argv[])
|
||||
" http-server-sync-ssl 0.0.0.0 8080 .\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto const address = boost::asio::ip::address::from_string(argv[1]);
|
||||
auto const address = boost::asio::ip::make_address(argv[1]);
|
||||
auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||
std::string const doc_root = argv[3];
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios{1};
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc{1};
|
||||
|
||||
// The SSL context is required, and holds certificates
|
||||
ssl::context ctx{ssl::context::sslv23};
|
||||
@ -325,11 +325,11 @@ int main(int argc, char* argv[])
|
||||
load_server_certificate(ctx);
|
||||
|
||||
// The acceptor receives incoming connections
|
||||
tcp::acceptor acceptor{ios, {address, port}};
|
||||
tcp::acceptor acceptor{ioc, {address, port}};
|
||||
for(;;)
|
||||
{
|
||||
// This will receive the new connection
|
||||
tcp::socket socket{ios};
|
||||
tcp::socket socket{ioc};
|
||||
|
||||
// Block until we get a connection
|
||||
acceptor.accept(socket);
|
||||
|
@ -298,19 +298,19 @@ int main(int argc, char* argv[])
|
||||
" http-server-sync 0.0.0.0 8080 .\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto const address = boost::asio::ip::address::from_string(argv[1]);
|
||||
auto const address = boost::asio::ip::make_address(argv[1]);
|
||||
auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||
std::string const doc_root = argv[3];
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios{1};
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc{1};
|
||||
|
||||
// The acceptor receives incoming connections
|
||||
tcp::acceptor acceptor{ios, {address, port}};
|
||||
tcp::acceptor acceptor{ioc, {address, port}};
|
||||
for(;;)
|
||||
{
|
||||
// This will receive the new connection
|
||||
tcp::socket socket{ios};
|
||||
tcp::socket socket{ioc};
|
||||
|
||||
// Block until we get a connection
|
||||
acceptor.accept(socket);
|
||||
|
@ -50,11 +50,11 @@ class session : public std::enable_shared_from_this<session>
|
||||
std::string text_;
|
||||
|
||||
public:
|
||||
// Resolver and socket require an io_service
|
||||
// Resolver and socket require an io_context
|
||||
explicit
|
||||
session(boost::asio::io_service& ios, ssl::context& ctx)
|
||||
: resolver_(ios)
|
||||
, ws_(ios, ctx)
|
||||
session(boost::asio::io_context& ioc, ssl::context& ctx)
|
||||
: resolver_(ioc)
|
||||
, ws_(ioc, ctx)
|
||||
{
|
||||
}
|
||||
|
||||
@ -70,7 +70,9 @@ public:
|
||||
text_ = text;
|
||||
|
||||
// Look up the domain name
|
||||
resolver_.async_resolve({host, port},
|
||||
resolver_.async_resolve(
|
||||
host,
|
||||
port,
|
||||
std::bind(
|
||||
&session::on_resolve,
|
||||
shared_from_this(),
|
||||
@ -81,7 +83,7 @@ public:
|
||||
void
|
||||
on_resolve(
|
||||
boost::system::error_code ec,
|
||||
tcp::resolver::iterator result)
|
||||
tcp::resolver::results_type results)
|
||||
{
|
||||
if(ec)
|
||||
return fail(ec, "resolve");
|
||||
@ -89,7 +91,8 @@ public:
|
||||
// Make the connection on the IP address we get from a lookup
|
||||
boost::asio::async_connect(
|
||||
ws_.next_layer().next_layer(),
|
||||
result,
|
||||
results.begin(),
|
||||
results.end(),
|
||||
std::bind(
|
||||
&session::on_connect,
|
||||
shared_from_this(),
|
||||
@ -209,8 +212,8 @@ int main(int argc, char** argv)
|
||||
auto const port = argv[2];
|
||||
auto const text = argv[3];
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios;
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc;
|
||||
|
||||
// The SSL context is required, and holds certificates
|
||||
ssl::context ctx{ssl::context::sslv23_client};
|
||||
@ -219,11 +222,11 @@ int main(int argc, char** argv)
|
||||
load_root_certificates(ctx);
|
||||
|
||||
// Launch the asynchronous operation
|
||||
std::make_shared<session>(ios, ctx)->run(host, port, text);
|
||||
std::make_shared<session>(ioc, ctx)->run(host, port, text);
|
||||
|
||||
// Run the I/O service. The call will return when
|
||||
// the get operation is complete.
|
||||
ios.run();
|
||||
ioc.run();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -45,11 +45,11 @@ class session : public std::enable_shared_from_this<session>
|
||||
std::string text_;
|
||||
|
||||
public:
|
||||
// Resolver and socket require an io_service
|
||||
// Resolver and socket require an io_context
|
||||
explicit
|
||||
session(boost::asio::io_service& ios)
|
||||
: resolver_(ios)
|
||||
, ws_(ios)
|
||||
session(boost::asio::io_context& ioc)
|
||||
: resolver_(ioc)
|
||||
, ws_(ioc)
|
||||
{
|
||||
}
|
||||
|
||||
@ -65,7 +65,9 @@ public:
|
||||
text_ = text;
|
||||
|
||||
// Look up the domain name
|
||||
resolver_.async_resolve({host, port},
|
||||
resolver_.async_resolve(
|
||||
host,
|
||||
port,
|
||||
std::bind(
|
||||
&session::on_resolve,
|
||||
shared_from_this(),
|
||||
@ -76,7 +78,7 @@ public:
|
||||
void
|
||||
on_resolve(
|
||||
boost::system::error_code ec,
|
||||
tcp::resolver::iterator result)
|
||||
tcp::resolver::results_type results)
|
||||
{
|
||||
if(ec)
|
||||
return fail(ec, "resolve");
|
||||
@ -84,7 +86,8 @@ public:
|
||||
// Make the connection on the IP address we get from a lookup
|
||||
boost::asio::async_connect(
|
||||
ws_.next_layer(),
|
||||
result,
|
||||
results.begin(),
|
||||
results.end(),
|
||||
std::bind(
|
||||
&session::on_connect,
|
||||
shared_from_this(),
|
||||
@ -189,15 +192,15 @@ int main(int argc, char** argv)
|
||||
auto const port = argv[2];
|
||||
auto const text = argv[3];
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios;
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc;
|
||||
|
||||
// Launch the asynchronous operation
|
||||
std::make_shared<session>(ios)->run(host, port, text);
|
||||
std::make_shared<session>(ioc)->run(host, port, text);
|
||||
|
||||
// Run the I/O service. The call will return when
|
||||
// the get operation is complete.
|
||||
ios.run();
|
||||
ioc.run();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -46,23 +46,23 @@ do_session(
|
||||
std::string const& host,
|
||||
std::string const& port,
|
||||
std::string const& text,
|
||||
boost::asio::io_service& ios,
|
||||
boost::asio::io_context& ioc,
|
||||
ssl::context& ctx,
|
||||
boost::asio::yield_context yield)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
|
||||
// These objects perform our I/O
|
||||
tcp::resolver resolver{ios};
|
||||
websocket::stream<ssl::stream<tcp::socket>> ws{ios, ctx};
|
||||
tcp::resolver resolver{ioc};
|
||||
websocket::stream<ssl::stream<tcp::socket>> ws{ioc, ctx};
|
||||
|
||||
// Look up the domain name
|
||||
auto const lookup = resolver.async_resolve({host, port}, yield[ec]);
|
||||
auto const results = resolver.async_resolve(host, port, yield[ec]);
|
||||
if(ec)
|
||||
return fail(ec, "resolve");
|
||||
|
||||
// Make the connection on the IP address we get from a lookup
|
||||
boost::asio::async_connect(ws.next_layer().next_layer(), lookup, yield[ec]);
|
||||
boost::asio::async_connect(ws.next_layer().next_layer(), results.begin(), results.end(), yield[ec]);
|
||||
if(ec)
|
||||
return fail(ec, "connect");
|
||||
|
||||
@ -117,8 +117,8 @@ int main(int argc, char** argv)
|
||||
auto const port = argv[2];
|
||||
auto const text = argv[3];
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios;
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc;
|
||||
|
||||
// The SSL context is required, and holds certificates
|
||||
ssl::context ctx{ssl::context::sslv23_client};
|
||||
@ -127,18 +127,18 @@ int main(int argc, char** argv)
|
||||
load_root_certificates(ctx);
|
||||
|
||||
// Launch the asynchronous operation
|
||||
boost::asio::spawn(ios, std::bind(
|
||||
boost::asio::spawn(ioc, std::bind(
|
||||
&do_session,
|
||||
std::string(host),
|
||||
std::string(port),
|
||||
std::string(text),
|
||||
std::ref(ios),
|
||||
std::ref(ioc),
|
||||
std::ref(ctx),
|
||||
std::placeholders::_1));
|
||||
|
||||
// Run the I/O service. The call will return when
|
||||
// the get operation is complete.
|
||||
ios.run();
|
||||
ioc.run();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -41,22 +41,22 @@ do_session(
|
||||
std::string const& host,
|
||||
std::string const& port,
|
||||
std::string const& text,
|
||||
boost::asio::io_service& ios,
|
||||
boost::asio::io_context& ioc,
|
||||
boost::asio::yield_context yield)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
|
||||
// These objects perform our I/O
|
||||
tcp::resolver resolver{ios};
|
||||
websocket::stream<tcp::socket> ws{ios};
|
||||
tcp::resolver resolver{ioc};
|
||||
websocket::stream<tcp::socket> ws{ioc};
|
||||
|
||||
// Look up the domain name
|
||||
auto const lookup = resolver.async_resolve({host, port}, yield[ec]);
|
||||
auto const results = resolver.async_resolve(host, port, yield[ec]);
|
||||
if(ec)
|
||||
return fail(ec, "resolve");
|
||||
|
||||
// Make the connection on the IP address we get from a lookup
|
||||
boost::asio::async_connect(ws.next_layer(), lookup, yield[ec]);
|
||||
boost::asio::async_connect(ws.next_layer(), results.begin(), results.end(), yield[ec]);
|
||||
if(ec)
|
||||
return fail(ec, "connect");
|
||||
|
||||
@ -106,21 +106,21 @@ int main(int argc, char** argv)
|
||||
auto const port = argv[2];
|
||||
auto const text = argv[3];
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios;
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc;
|
||||
|
||||
// Launch the asynchronous operation
|
||||
boost::asio::spawn(ios, std::bind(
|
||||
boost::asio::spawn(ioc, std::bind(
|
||||
&do_session,
|
||||
std::string(host),
|
||||
std::string(port),
|
||||
std::string(text),
|
||||
std::ref(ios),
|
||||
std::ref(ioc),
|
||||
std::placeholders::_1));
|
||||
|
||||
// Run the I/O service. The call will return when
|
||||
// the get operation is complete.
|
||||
ios.run();
|
||||
ioc.run();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -47,8 +47,8 @@ int main(int argc, char** argv)
|
||||
auto const port = argv[2];
|
||||
auto const text = argv[3];
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios;
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc;
|
||||
|
||||
// The SSL context is required, and holds certificates
|
||||
ssl::context ctx{ssl::context::sslv23_client};
|
||||
@ -57,14 +57,14 @@ int main(int argc, char** argv)
|
||||
load_root_certificates(ctx);
|
||||
|
||||
// These objects perform our I/O
|
||||
tcp::resolver resolver{ios};
|
||||
websocket::stream<ssl::stream<tcp::socket>> ws{ios, ctx};
|
||||
tcp::resolver resolver{ioc};
|
||||
websocket::stream<ssl::stream<tcp::socket>> ws{ioc, ctx};
|
||||
|
||||
// Look up the domain name
|
||||
auto const lookup = resolver.resolve({host, port});
|
||||
auto const results = resolver.resolve(host, port);
|
||||
|
||||
// Make the connection on the IP address we get from a lookup
|
||||
boost::asio::connect(ws.next_layer().next_layer(), lookup);
|
||||
boost::asio::connect(ws.next_layer().next_layer(), results.begin(), results.end());
|
||||
|
||||
// Perform the SSL handshake
|
||||
ws.next_layer().handshake(ssl::stream_base::client);
|
||||
|
@ -44,18 +44,18 @@ int main(int argc, char** argv)
|
||||
auto const port = argv[2];
|
||||
auto const text = argv[3];
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios;
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc;
|
||||
|
||||
// These objects perform our I/O
|
||||
tcp::resolver resolver{ios};
|
||||
websocket::stream<tcp::socket> ws{ios};
|
||||
tcp::resolver resolver{ioc};
|
||||
websocket::stream<tcp::socket> ws{ioc};
|
||||
|
||||
// Look up the domain name
|
||||
auto const lookup = resolver.resolve({host, port});
|
||||
auto const results = resolver.resolve(host, port);
|
||||
|
||||
// Make the connection on the IP address we get from a lookup
|
||||
boost::asio::connect(ws.next_layer(), lookup);
|
||||
boost::asio::connect(ws.next_layer(), results.begin(), results.end());
|
||||
|
||||
// Perform the websocket handshake
|
||||
ws.handshake(host, "/");
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <boost/beast/core.hpp>
|
||||
#include <boost/beast/websocket.hpp>
|
||||
#include <boost/beast/websocket/ssl.hpp>
|
||||
#include <boost/asio/bind_executor.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/ssl/stream.hpp>
|
||||
@ -48,7 +49,8 @@ class session : public std::enable_shared_from_this<session>
|
||||
{
|
||||
tcp::socket socket_;
|
||||
websocket::stream<ssl::stream<tcp::socket&>> ws_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::strand<
|
||||
boost::asio::io_context::executor_type> strand_;
|
||||
boost::beast::multi_buffer buffer_;
|
||||
|
||||
public:
|
||||
@ -56,7 +58,7 @@ public:
|
||||
session(tcp::socket socket, ssl::context& ctx)
|
||||
: socket_(std::move(socket))
|
||||
, ws_(socket_, ctx)
|
||||
, strand_(ws_.get_io_service())
|
||||
, strand_(ws_.get_executor())
|
||||
{
|
||||
}
|
||||
|
||||
@ -67,10 +69,12 @@ public:
|
||||
// Perform the SSL handshake
|
||||
ws_.next_layer().async_handshake(
|
||||
ssl::stream_base::server,
|
||||
strand_.wrap(std::bind(
|
||||
&session::on_handshake,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&session::on_handshake,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -81,10 +85,12 @@ public:
|
||||
|
||||
// Accept the websocket handshake
|
||||
ws_.async_accept(
|
||||
strand_.wrap(std::bind(
|
||||
&session::on_accept,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&session::on_accept,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -103,11 +109,13 @@ public:
|
||||
// Read a message into our buffer
|
||||
ws_.async_read(
|
||||
buffer_,
|
||||
strand_.wrap(std::bind(
|
||||
&session::on_read,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&session::on_read,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -128,11 +136,13 @@ public:
|
||||
ws_.text(ws_.got_text());
|
||||
ws_.async_write(
|
||||
buffer_.data(),
|
||||
strand_.wrap(std::bind(
|
||||
&session::on_write,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&session::on_write,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -164,12 +174,12 @@ class listener : public std::enable_shared_from_this<listener>
|
||||
|
||||
public:
|
||||
listener(
|
||||
boost::asio::io_service& ios,
|
||||
boost::asio::io_context& ioc,
|
||||
ssl::context& ctx,
|
||||
tcp::endpoint endpoint)
|
||||
: ctx_(ctx)
|
||||
, acceptor_(ios)
|
||||
, socket_(ios)
|
||||
, acceptor_(ioc)
|
||||
, socket_(ioc)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
|
||||
@ -191,7 +201,7 @@ public:
|
||||
|
||||
// Start listening for connections
|
||||
acceptor_.listen(
|
||||
boost::asio::socket_base::max_connections, ec);
|
||||
boost::asio::socket_base::max_listen_connections, ec);
|
||||
if(ec)
|
||||
{
|
||||
fail(ec, "listen");
|
||||
@ -250,12 +260,12 @@ int main(int argc, char* argv[])
|
||||
" websocket-server-async-ssl 0.0.0.0 8080 1\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto const address = boost::asio::ip::address::from_string(argv[1]);
|
||||
auto const address = boost::asio::ip::make_address(argv[1]);
|
||||
auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||
auto const threads = std::max<std::size_t>(1, std::atoi(argv[3]));
|
||||
auto const threads = std::max<int>(1, std::atoi(argv[3]));
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios{threads};
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc{threads};
|
||||
|
||||
// The SSL context is required, and holds certificates
|
||||
ssl::context ctx{ssl::context::sslv23};
|
||||
@ -264,18 +274,18 @@ int main(int argc, char* argv[])
|
||||
load_server_certificate(ctx);
|
||||
|
||||
// Create and launch a listening port
|
||||
std::make_shared<listener>(ios, ctx, tcp::endpoint{address, port})->run();
|
||||
std::make_shared<listener>(ioc, ctx, tcp::endpoint{address, port})->run();
|
||||
|
||||
// Run the I/O service on the requested number of threads
|
||||
std::vector<std::thread> v;
|
||||
v.reserve(threads - 1);
|
||||
for(auto i = threads - 1; i > 0; --i)
|
||||
v.emplace_back(
|
||||
[&ios]
|
||||
[&ioc]
|
||||
{
|
||||
ios.run();
|
||||
ioc.run();
|
||||
});
|
||||
ios.run();
|
||||
ioc.run();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include <boost/beast/core.hpp>
|
||||
#include <boost/beast/websocket.hpp>
|
||||
#include <boost/asio/bind_executor.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <algorithm>
|
||||
@ -42,7 +43,8 @@ fail(boost::system::error_code ec, char const* what)
|
||||
class session : public std::enable_shared_from_this<session>
|
||||
{
|
||||
websocket::stream<tcp::socket> ws_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::strand<
|
||||
boost::asio::io_context::executor_type> strand_;
|
||||
boost::beast::multi_buffer buffer_;
|
||||
|
||||
public:
|
||||
@ -50,7 +52,7 @@ public:
|
||||
explicit
|
||||
session(tcp::socket socket)
|
||||
: ws_(std::move(socket))
|
||||
, strand_(ws_.get_io_service())
|
||||
, strand_(ws_.get_executor())
|
||||
{
|
||||
}
|
||||
|
||||
@ -60,10 +62,12 @@ public:
|
||||
{
|
||||
// Accept the websocket handshake
|
||||
ws_.async_accept(
|
||||
strand_.wrap(std::bind(
|
||||
&session::on_accept,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&session::on_accept,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -82,11 +86,13 @@ public:
|
||||
// Read a message into our buffer
|
||||
ws_.async_read(
|
||||
buffer_,
|
||||
strand_.wrap(std::bind(
|
||||
&session::on_read,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&session::on_read,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -107,11 +113,13 @@ public:
|
||||
ws_.text(ws_.got_text());
|
||||
ws_.async_write(
|
||||
buffer_.data(),
|
||||
strand_.wrap(std::bind(
|
||||
&session::on_write,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&session::on_write,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -142,10 +150,10 @@ class listener : public std::enable_shared_from_this<listener>
|
||||
|
||||
public:
|
||||
listener(
|
||||
boost::asio::io_service& ios,
|
||||
boost::asio::io_context& ioc,
|
||||
tcp::endpoint endpoint)
|
||||
: acceptor_(ios)
|
||||
, socket_(ios)
|
||||
: acceptor_(ioc)
|
||||
, socket_(ioc)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
|
||||
@ -167,7 +175,7 @@ public:
|
||||
|
||||
// Start listening for connections
|
||||
acceptor_.listen(
|
||||
boost::asio::socket_base::max_connections, ec);
|
||||
boost::asio::socket_base::max_listen_connections, ec);
|
||||
if(ec)
|
||||
{
|
||||
fail(ec, "listen");
|
||||
@ -226,26 +234,26 @@ int main(int argc, char* argv[])
|
||||
" websocket-server-async 0.0.0.0 8080 1\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto const address = boost::asio::ip::address::from_string(argv[1]);
|
||||
auto const address = boost::asio::ip::make_address(argv[1]);
|
||||
auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||
auto const threads = std::max<std::size_t>(1, std::atoi(argv[3]));
|
||||
auto const threads = std::max<int>(1, std::atoi(argv[3]));
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios{threads};
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc{threads};
|
||||
|
||||
// Create and launch a listening port
|
||||
std::make_shared<listener>(ios, tcp::endpoint{address, port})->run();
|
||||
std::make_shared<listener>(ioc, tcp::endpoint{address, port})->run();
|
||||
|
||||
// Run the I/O service on the requested number of threads
|
||||
std::vector<std::thread> v;
|
||||
v.reserve(threads - 1);
|
||||
for(auto i = threads - 1; i > 0; --i)
|
||||
v.emplace_back(
|
||||
[&ios]
|
||||
[&ioc]
|
||||
{
|
||||
ios.run();
|
||||
ioc.run();
|
||||
});
|
||||
ios.run();
|
||||
ioc.run();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ do_session(
|
||||
// Accepts incoming connections and launches the sessions
|
||||
void
|
||||
do_listen(
|
||||
boost::asio::io_service& ios,
|
||||
boost::asio::io_context& ioc,
|
||||
ssl::context& ctx,
|
||||
tcp::endpoint endpoint,
|
||||
boost::asio::yield_context yield)
|
||||
@ -101,7 +101,7 @@ do_listen(
|
||||
boost::system::error_code ec;
|
||||
|
||||
// Open the acceptor
|
||||
tcp::acceptor acceptor(ios);
|
||||
tcp::acceptor acceptor(ioc);
|
||||
acceptor.open(endpoint.protocol(), ec);
|
||||
if(ec)
|
||||
return fail(ec, "open");
|
||||
@ -112,19 +112,19 @@ do_listen(
|
||||
return fail(ec, "bind");
|
||||
|
||||
// Start listening for connections
|
||||
acceptor.listen(boost::asio::socket_base::max_connections, ec);
|
||||
acceptor.listen(boost::asio::socket_base::max_listen_connections, ec);
|
||||
if(ec)
|
||||
return fail(ec, "listen");
|
||||
|
||||
for(;;)
|
||||
{
|
||||
tcp::socket socket(ios);
|
||||
tcp::socket socket(ioc);
|
||||
acceptor.async_accept(socket, yield[ec]);
|
||||
if(ec)
|
||||
fail(ec, "accept");
|
||||
else
|
||||
boost::asio::spawn(
|
||||
acceptor.get_io_service(),
|
||||
acceptor.get_executor().context(),
|
||||
std::bind(
|
||||
&do_session,
|
||||
std::move(socket),
|
||||
@ -144,12 +144,12 @@ int main(int argc, char* argv[])
|
||||
" websocket-server-coro-ssl 0.0.0.0 8080 1\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto const address = boost::asio::ip::address::from_string(argv[1]);
|
||||
auto const address = boost::asio::ip::make_address(argv[1]);
|
||||
auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||
auto const threads = std::max<std::size_t>(1, std::atoi(argv[3]));
|
||||
auto const threads = std::max<int>(1, std::atoi(argv[3]));
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios{threads};
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc{threads};
|
||||
|
||||
// The SSL context is required, and holds certificates
|
||||
ssl::context ctx{ssl::context::sslv23};
|
||||
@ -158,10 +158,10 @@ int main(int argc, char* argv[])
|
||||
load_server_certificate(ctx);
|
||||
|
||||
// Spawn a listening port
|
||||
boost::asio::spawn(ios,
|
||||
boost::asio::spawn(ioc,
|
||||
std::bind(
|
||||
&do_listen,
|
||||
std::ref(ios),
|
||||
std::ref(ioc),
|
||||
std::ref(ctx),
|
||||
tcp::endpoint{address, port},
|
||||
std::placeholders::_1));
|
||||
@ -171,11 +171,11 @@ int main(int argc, char* argv[])
|
||||
v.reserve(threads - 1);
|
||||
for(auto i = threads - 1; i > 0; --i)
|
||||
v.emplace_back(
|
||||
[&ios]
|
||||
[&ioc]
|
||||
{
|
||||
ios.run();
|
||||
ioc.run();
|
||||
});
|
||||
ios.run();
|
||||
ioc.run();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -80,14 +80,14 @@ do_session(tcp::socket& socket, boost::asio::yield_context yield)
|
||||
// Accepts incoming connections and launches the sessions
|
||||
void
|
||||
do_listen(
|
||||
boost::asio::io_service& ios,
|
||||
boost::asio::io_context& ioc,
|
||||
tcp::endpoint endpoint,
|
||||
boost::asio::yield_context yield)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
|
||||
// Open the acceptor
|
||||
tcp::acceptor acceptor(ios);
|
||||
tcp::acceptor acceptor(ioc);
|
||||
acceptor.open(endpoint.protocol(), ec);
|
||||
if(ec)
|
||||
return fail(ec, "open");
|
||||
@ -98,19 +98,19 @@ do_listen(
|
||||
return fail(ec, "bind");
|
||||
|
||||
// Start listening for connections
|
||||
acceptor.listen(boost::asio::socket_base::max_connections, ec);
|
||||
acceptor.listen(boost::asio::socket_base::max_listen_connections, ec);
|
||||
if(ec)
|
||||
return fail(ec, "listen");
|
||||
|
||||
for(;;)
|
||||
{
|
||||
tcp::socket socket(ios);
|
||||
tcp::socket socket(ioc);
|
||||
acceptor.async_accept(socket, yield[ec]);
|
||||
if(ec)
|
||||
fail(ec, "accept");
|
||||
else
|
||||
boost::asio::spawn(
|
||||
acceptor.get_io_service(),
|
||||
acceptor.get_executor().context(),
|
||||
std::bind(
|
||||
&do_session,
|
||||
std::move(socket),
|
||||
@ -129,18 +129,18 @@ int main(int argc, char* argv[])
|
||||
" websocket-server-coro 0.0.0.0 8080 1\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto const address = boost::asio::ip::address::from_string(argv[1]);
|
||||
auto const address = boost::asio::ip::make_address(argv[1]);
|
||||
auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||
auto const threads = std::max<std::size_t>(1, std::atoi(argv[3]));
|
||||
auto const threads = std::max<int>(1, std::atoi(argv[3]));
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios{threads};
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc{threads};
|
||||
|
||||
// Spawn a listening port
|
||||
boost::asio::spawn(ios,
|
||||
boost::asio::spawn(ioc,
|
||||
std::bind(
|
||||
&do_listen,
|
||||
std::ref(ios),
|
||||
std::ref(ioc),
|
||||
tcp::endpoint{address, port},
|
||||
std::placeholders::_1));
|
||||
|
||||
@ -149,11 +149,11 @@ int main(int argc, char* argv[])
|
||||
v.reserve(threads - 1);
|
||||
for(auto i = threads - 1; i > 0; --i)
|
||||
v.emplace_back(
|
||||
[&ios]
|
||||
[&ioc]
|
||||
{
|
||||
ios.run();
|
||||
ioc.run();
|
||||
});
|
||||
ios.run();
|
||||
ioc.run();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <boost/beast/http.hpp>
|
||||
#include <boost/beast/version.hpp>
|
||||
#include <boost/beast/websocket.hpp>
|
||||
#include <boost/asio/bind_executor.hpp>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
@ -113,14 +114,14 @@ do_sync_session(tcp::socket& socket)
|
||||
|
||||
void
|
||||
do_sync_listen(
|
||||
boost::asio::io_service& ios,
|
||||
boost::asio::io_context& ioc,
|
||||
tcp::endpoint endpoint)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
tcp::acceptor acceptor{ios, endpoint};
|
||||
tcp::acceptor acceptor{ioc, endpoint};
|
||||
for(;;)
|
||||
{
|
||||
tcp::socket socket{ios};
|
||||
tcp::socket socket{ioc};
|
||||
|
||||
acceptor.accept(socket, ec);
|
||||
if(ec)
|
||||
@ -138,7 +139,8 @@ do_sync_listen(
|
||||
class async_session : public std::enable_shared_from_this<async_session>
|
||||
{
|
||||
websocket::stream<tcp::socket> ws_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::strand<
|
||||
boost::asio::io_context::executor_type> strand_;
|
||||
boost::beast::multi_buffer buffer_;
|
||||
|
||||
public:
|
||||
@ -146,7 +148,7 @@ public:
|
||||
explicit
|
||||
async_session(tcp::socket socket)
|
||||
: ws_(std::move(socket))
|
||||
, strand_(ws_.get_io_service())
|
||||
, strand_(ws_.get_executor())
|
||||
{
|
||||
setup_stream(ws_);
|
||||
}
|
||||
@ -162,10 +164,12 @@ public:
|
||||
res.set(http::field::server,
|
||||
"Boost.Beast.async/" + std::to_string(BOOST_BEAST_VERSION));
|
||||
},
|
||||
strand_.wrap(std::bind(
|
||||
&async_session::on_accept,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&async_session::on_accept,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -184,11 +188,13 @@ public:
|
||||
// Read a message into our buffer
|
||||
ws_.async_read(
|
||||
buffer_,
|
||||
strand_.wrap(std::bind(
|
||||
&async_session::on_read,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&async_session::on_read,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -209,11 +215,13 @@ public:
|
||||
ws_.text(ws_.got_text());
|
||||
ws_.async_write(
|
||||
buffer_.data(),
|
||||
strand_.wrap(std::bind(
|
||||
&async_session::on_write,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&async_session::on_write,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -237,17 +245,18 @@ public:
|
||||
// Accepts incoming connections and launches the sessions
|
||||
class async_listener : public std::enable_shared_from_this<async_listener>
|
||||
{
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::strand<
|
||||
boost::asio::io_context::executor_type> strand_;
|
||||
tcp::acceptor acceptor_;
|
||||
tcp::socket socket_;
|
||||
|
||||
public:
|
||||
async_listener(
|
||||
boost::asio::io_service& ios,
|
||||
boost::asio::io_context& ioc,
|
||||
tcp::endpoint endpoint)
|
||||
: strand_(ios)
|
||||
, acceptor_(ios)
|
||||
, socket_(ios)
|
||||
: strand_(ioc.get_executor())
|
||||
, acceptor_(ioc)
|
||||
, socket_(ioc)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
|
||||
@ -269,7 +278,7 @@ public:
|
||||
|
||||
// Start listening for connections
|
||||
acceptor_.listen(
|
||||
boost::asio::socket_base::max_connections, ec);
|
||||
boost::asio::socket_base::max_listen_connections, ec);
|
||||
if(ec)
|
||||
{
|
||||
fail(ec, "listen");
|
||||
@ -291,10 +300,12 @@ public:
|
||||
{
|
||||
acceptor_.async_accept(
|
||||
socket_,
|
||||
strand_.wrap(std::bind(
|
||||
&async_listener::on_accept,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&async_listener::on_accept,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -354,13 +365,13 @@ do_coro_session(tcp::socket& socket, boost::asio::yield_context yield)
|
||||
|
||||
void
|
||||
do_coro_listen(
|
||||
boost::asio::io_service& ios,
|
||||
boost::asio::io_context& ioc,
|
||||
tcp::endpoint endpoint,
|
||||
boost::asio::yield_context yield)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
|
||||
tcp::acceptor acceptor(ios);
|
||||
tcp::acceptor acceptor(ioc);
|
||||
acceptor.open(endpoint.protocol(), ec);
|
||||
if(ec)
|
||||
return fail(ec, "open");
|
||||
@ -369,13 +380,13 @@ do_coro_listen(
|
||||
if(ec)
|
||||
return fail(ec, "bind");
|
||||
|
||||
acceptor.listen(boost::asio::socket_base::max_connections, ec);
|
||||
acceptor.listen(boost::asio::socket_base::max_listen_connections, ec);
|
||||
if(ec)
|
||||
return fail(ec, "listen");
|
||||
|
||||
for(;;)
|
||||
{
|
||||
tcp::socket socket(ios);
|
||||
tcp::socket socket(ioc);
|
||||
|
||||
acceptor.async_accept(socket, yield[ec]);
|
||||
if(ec)
|
||||
@ -385,7 +396,7 @@ do_coro_listen(
|
||||
}
|
||||
|
||||
boost::asio::spawn(
|
||||
acceptor.get_io_service(),
|
||||
acceptor.get_executor().context(),
|
||||
std::bind(
|
||||
&do_coro_session,
|
||||
std::move(socket),
|
||||
@ -410,17 +421,17 @@ int main(int argc, char* argv[])
|
||||
" starting-port+2 for coroutine.\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto const address = boost::asio::ip::address::from_string(argv[1]);
|
||||
auto const address = boost::asio::ip::make_address(argv[1]);
|
||||
auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||
auto const threads = std::max<std::size_t>(1, std::atoi(argv[3]));
|
||||
auto const threads = std::max<int>(1, std::atoi(argv[3]));
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios{threads};
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc{threads};
|
||||
|
||||
// Create sync port
|
||||
std::thread(std::bind(
|
||||
&do_sync_listen,
|
||||
std::ref(ios),
|
||||
std::ref(ioc),
|
||||
tcp::endpoint{
|
||||
address,
|
||||
static_cast<unsigned short>(port + 0u)}
|
||||
@ -428,16 +439,16 @@ int main(int argc, char* argv[])
|
||||
|
||||
// Create async port
|
||||
std::make_shared<async_listener>(
|
||||
ios,
|
||||
ioc,
|
||||
tcp::endpoint{
|
||||
address,
|
||||
static_cast<unsigned short>(port + 1u)})->run();
|
||||
|
||||
// Create coro port
|
||||
boost::asio::spawn(ios,
|
||||
boost::asio::spawn(ioc,
|
||||
std::bind(
|
||||
&do_coro_listen,
|
||||
std::ref(ios),
|
||||
std::ref(ioc),
|
||||
tcp::endpoint{
|
||||
address,
|
||||
static_cast<unsigned short>(port + 2u)},
|
||||
@ -448,11 +459,11 @@ int main(int argc, char* argv[])
|
||||
v.reserve(threads - 1);
|
||||
for(auto i = threads - 1; i > 0; --i)
|
||||
v.emplace_back(
|
||||
[&ios]
|
||||
[&ioc]
|
||||
{
|
||||
ios.run();
|
||||
ioc.run();
|
||||
});
|
||||
ios.run();
|
||||
ioc.run();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <boost/beast/core.hpp>
|
||||
#include <boost/beast/websocket.hpp>
|
||||
#include <boost/beast/websocket/ssl.hpp>
|
||||
#include <boost/asio/bind_executor.hpp>
|
||||
#include <boost/asio/coroutine.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/ssl/stream.hpp>
|
||||
@ -51,7 +52,8 @@ class session
|
||||
{
|
||||
tcp::socket socket_;
|
||||
websocket::stream<ssl::stream<tcp::socket&>> ws_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::strand<
|
||||
boost::asio::io_context::executor_type> strand_;
|
||||
boost::beast::multi_buffer buffer_;
|
||||
|
||||
public:
|
||||
@ -59,7 +61,7 @@ public:
|
||||
session(tcp::socket socket, ssl::context& ctx)
|
||||
: socket_(std::move(socket))
|
||||
, ws_(socket_, ctx)
|
||||
, strand_(ws_.get_io_service())
|
||||
, strand_(ws_.get_executor())
|
||||
{
|
||||
}
|
||||
|
||||
@ -83,21 +85,25 @@ public:
|
||||
// Perform the SSL handshake
|
||||
yield ws_.next_layer().async_handshake(
|
||||
ssl::stream_base::server,
|
||||
strand_.wrap(std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
0)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
0)));
|
||||
if(ec)
|
||||
return fail(ec, "handshake");
|
||||
|
||||
// Accept the websocket handshake
|
||||
yield ws_.async_accept(
|
||||
strand_.wrap(std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
0)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
0)));
|
||||
if(ec)
|
||||
return fail(ec, "accept");
|
||||
|
||||
@ -106,11 +112,13 @@ public:
|
||||
// Read a message into our buffer
|
||||
yield ws_.async_read(
|
||||
buffer_,
|
||||
strand_.wrap(std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
if(ec == websocket::error::closed)
|
||||
{
|
||||
// This indicates that the session was closed
|
||||
@ -123,11 +131,13 @@ public:
|
||||
ws_.text(ws_.got_text());
|
||||
yield ws_.async_write(
|
||||
buffer_.data(),
|
||||
strand_.wrap(std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
if(ec)
|
||||
return fail(ec, "write");
|
||||
|
||||
@ -152,12 +162,12 @@ class listener
|
||||
|
||||
public:
|
||||
listener(
|
||||
boost::asio::io_service& ios,
|
||||
boost::asio::io_context& ioc,
|
||||
ssl::context& ctx,
|
||||
tcp::endpoint endpoint)
|
||||
: ctx_(ctx)
|
||||
, acceptor_(ios)
|
||||
, socket_(ios)
|
||||
, acceptor_(ioc)
|
||||
, socket_(ioc)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
|
||||
@ -179,7 +189,7 @@ public:
|
||||
|
||||
// Start listening for connections
|
||||
acceptor_.listen(
|
||||
boost::asio::socket_base::max_connections, ec);
|
||||
boost::asio::socket_base::max_listen_connections, ec);
|
||||
if(ec)
|
||||
{
|
||||
fail(ec, "listen");
|
||||
@ -238,12 +248,12 @@ int main(int argc, char* argv[])
|
||||
" websocket-server-async-ssl 0.0.0.0 8080 1\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto const address = boost::asio::ip::address::from_string(argv[1]);
|
||||
auto const address = boost::asio::ip::make_address(argv[1]);
|
||||
auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||
auto const threads = std::max<std::size_t>(1, std::atoi(argv[3]));
|
||||
auto const threads = std::max<int>(1, std::atoi(argv[3]));
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios{threads};
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc{threads};
|
||||
|
||||
// The SSL context is required, and holds certificates
|
||||
ssl::context ctx{ssl::context::sslv23};
|
||||
@ -252,18 +262,18 @@ int main(int argc, char* argv[])
|
||||
load_server_certificate(ctx);
|
||||
|
||||
// Create and launch a listening port
|
||||
std::make_shared<listener>(ios, ctx, tcp::endpoint{address, port})->run();
|
||||
std::make_shared<listener>(ioc, ctx, tcp::endpoint{address, port})->run();
|
||||
|
||||
// Run the I/O service on the requested number of threads
|
||||
std::vector<std::thread> v;
|
||||
v.reserve(threads - 1);
|
||||
for(auto i = threads - 1; i > 0; --i)
|
||||
v.emplace_back(
|
||||
[&ios]
|
||||
[&ioc]
|
||||
{
|
||||
ios.run();
|
||||
ioc.run();
|
||||
});
|
||||
ios.run();
|
||||
ioc.run();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include <boost/beast/core.hpp>
|
||||
#include <boost/beast/websocket.hpp>
|
||||
#include <boost/asio/bind_executor.hpp>
|
||||
#include <boost/asio/coroutine.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
@ -45,7 +46,8 @@ class session
|
||||
, public std::enable_shared_from_this<session>
|
||||
{
|
||||
websocket::stream<tcp::socket> ws_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::strand<
|
||||
boost::asio::io_context::executor_type> strand_;
|
||||
boost::beast::multi_buffer buffer_;
|
||||
|
||||
public:
|
||||
@ -53,7 +55,7 @@ public:
|
||||
explicit
|
||||
session(tcp::socket socket)
|
||||
: ws_(std::move(socket))
|
||||
, strand_(ws_.get_io_service())
|
||||
, strand_(ws_.get_executor())
|
||||
{
|
||||
}
|
||||
|
||||
@ -75,11 +77,13 @@ public:
|
||||
{
|
||||
// Accept the websocket handshake
|
||||
yield ws_.async_accept(
|
||||
strand_.wrap(std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
0)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
0)));
|
||||
if(ec)
|
||||
return fail(ec, "accept");
|
||||
|
||||
@ -88,11 +92,13 @@ public:
|
||||
// Read a message into our buffer
|
||||
yield ws_.async_read(
|
||||
buffer_,
|
||||
strand_.wrap(std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
if(ec == websocket::error::closed)
|
||||
{
|
||||
// This indicates that the session was closed
|
||||
@ -105,11 +111,13 @@ public:
|
||||
ws_.text(ws_.got_text());
|
||||
yield ws_.async_write(
|
||||
buffer_.data(),
|
||||
strand_.wrap(std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
boost::asio::bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
if(ec)
|
||||
return fail(ec, "write");
|
||||
|
||||
@ -133,10 +141,10 @@ class listener
|
||||
|
||||
public:
|
||||
listener(
|
||||
boost::asio::io_service& ios,
|
||||
boost::asio::io_context& ioc,
|
||||
tcp::endpoint endpoint)
|
||||
: acceptor_(ios)
|
||||
, socket_(ios)
|
||||
: acceptor_(ioc)
|
||||
, socket_(ioc)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
|
||||
@ -158,7 +166,7 @@ public:
|
||||
|
||||
// Start listening for connections
|
||||
acceptor_.listen(
|
||||
boost::asio::socket_base::max_connections, ec);
|
||||
boost::asio::socket_base::max_listen_connections, ec);
|
||||
if(ec)
|
||||
{
|
||||
fail(ec, "listen");
|
||||
@ -217,26 +225,26 @@ int main(int argc, char* argv[])
|
||||
" websocket-server-stackless 0.0.0.0 8080 1\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto const address = boost::asio::ip::address::from_string(argv[1]);
|
||||
auto const address = boost::asio::ip::make_address(argv[1]);
|
||||
auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||
auto const threads = std::max<std::size_t>(1, std::atoi(argv[3]));
|
||||
auto const threads = std::max<int>(1, std::atoi(argv[3]));
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios{threads};
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc{threads};
|
||||
|
||||
// Create and launch a listening port
|
||||
std::make_shared<listener>(ios, tcp::endpoint{address, port})->run();
|
||||
std::make_shared<listener>(ioc, tcp::endpoint{address, port})->run();
|
||||
|
||||
// Run the I/O service on the requested number of threads
|
||||
std::vector<std::thread> v;
|
||||
v.reserve(threads - 1);
|
||||
for(auto i = threads - 1; i > 0; --i)
|
||||
v.emplace_back(
|
||||
[&ios]
|
||||
[&ioc]
|
||||
{
|
||||
ios.run();
|
||||
ioc.run();
|
||||
});
|
||||
ios.run();
|
||||
ioc.run();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -87,11 +87,11 @@ int main(int argc, char* argv[])
|
||||
" websocket-server-sync-ssl 0.0.0.0 8080\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto const address = boost::asio::ip::address::from_string(argv[1]);
|
||||
auto const address = boost::asio::ip::make_address(argv[1]);
|
||||
auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios{1};
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc{1};
|
||||
|
||||
// The SSL context is required, and holds certificates
|
||||
ssl::context ctx{ssl::context::sslv23};
|
||||
@ -100,11 +100,11 @@ int main(int argc, char* argv[])
|
||||
load_server_certificate(ctx);
|
||||
|
||||
// The acceptor receives incoming connections
|
||||
tcp::acceptor acceptor{ios, {address, port}};
|
||||
tcp::acceptor acceptor{ioc, {address, port}};
|
||||
for(;;)
|
||||
{
|
||||
// This will receive the new connection
|
||||
tcp::socket socket{ios};
|
||||
tcp::socket socket{ioc};
|
||||
|
||||
// Block until we get a connection
|
||||
acceptor.accept(socket);
|
||||
|
@ -79,18 +79,18 @@ int main(int argc, char* argv[])
|
||||
" websocket-server-sync 0.0.0.0 8080\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto const address = boost::asio::ip::address::from_string(argv[1]);
|
||||
auto const address = boost::asio::ip::make_address(argv[1]);
|
||||
auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||
|
||||
// The io_service is required for all I/O
|
||||
boost::asio::io_service ios{1};
|
||||
// The io_context is required for all I/O
|
||||
boost::asio::io_context ioc{1};
|
||||
|
||||
// The acceptor receives incoming connections
|
||||
tcp::acceptor acceptor{ios, {address, port}};
|
||||
tcp::acceptor acceptor{ioc, {address, port}};
|
||||
for(;;)
|
||||
{
|
||||
// This will receive the new connection
|
||||
tcp::socket socket{ios};
|
||||
tcp::socket socket{ioc};
|
||||
|
||||
// Block until we get a connection
|
||||
acceptor.accept(socket);
|
||||
|
@ -12,7 +12,6 @@
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
|
||||
#include <boost/beast/core/async_result.hpp>
|
||||
#include <boost/beast/core/bind_handler.hpp>
|
||||
#include <boost/beast/core/buffered_read_stream.hpp>
|
||||
#include <boost/beast/core/buffers_adapter.hpp>
|
||||
@ -28,7 +27,6 @@
|
||||
#include <boost/beast/core/file_win32.hpp>
|
||||
#include <boost/beast/core/flat_buffer.hpp>
|
||||
#include <boost/beast/core/flat_static_buffer.hpp>
|
||||
#include <boost/beast/core/handler_alloc.hpp>
|
||||
#include <boost/beast/core/handler_ptr.hpp>
|
||||
#include <boost/beast/core/multi_buffer.hpp>
|
||||
#include <boost/beast/core/ostream.hpp>
|
||||
|
@ -1,209 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2016-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)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/beast
|
||||
//
|
||||
|
||||
#ifndef BOOST_BEAST_ASYNC_COMPLETION_HPP
|
||||
#define BOOST_BEAST_ASYNC_COMPLETION_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/beast/core/type_traits.hpp>
|
||||
#include <boost/asio/async_result.hpp>
|
||||
#include <boost/asio/handler_type.hpp>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
|
||||
/** An interface for customising the behaviour of an asynchronous initiation function.
|
||||
|
||||
This class is used for determining:
|
||||
|
||||
@li The concrete completion handler type to be called at the end of the
|
||||
asynchronous operation;
|
||||
|
||||
@li the initiating function return type; and
|
||||
|
||||
@li how the return value of the initiating function is obtained.
|
||||
|
||||
The trait allows the handler and return types to be determined at the point
|
||||
where the specific completion handler signature is known.
|
||||
|
||||
This template takes advantage of specializations of both
|
||||
`boost::asio::async_result` and `boost::asio::handler_type` for user-defined
|
||||
completion token types. The primary template assumes that the
|
||||
@b CompletionToken is the completion handler.
|
||||
|
||||
@par Example
|
||||
|
||||
The example shows how to define an asynchronous initiation function
|
||||
whose completion handler receives an error code:
|
||||
|
||||
@code
|
||||
template<
|
||||
class AsyncStream, // A stream supporting asynchronous read and write
|
||||
class Handler // The handler to call with signature void(error_code)
|
||||
>
|
||||
async_return_type< // This provides the return type customization
|
||||
Handler, void(error_code)>
|
||||
do_async(
|
||||
AsyncStream& stream, // The stream to work on
|
||||
Handler&& handler) // Could be an rvalue or const reference
|
||||
{
|
||||
// Make sure we have an async stream
|
||||
static_assert(is_async_stream<AsyncWriteStream>::value,
|
||||
"AsyncStream requirements not met");
|
||||
|
||||
// This helper converts the handler into the real handler type
|
||||
async_completion<WriteHandler, void(error_code)> init{handler};
|
||||
|
||||
... // Create and invoke the composed operation
|
||||
|
||||
// This provides the return value and executor customization
|
||||
return init.result.get();
|
||||
}
|
||||
@endcode
|
||||
|
||||
@see @ref async_completion, @ref async_return_type, @ref handler_type
|
||||
*/
|
||||
template<class CompletionToken, class Signature>
|
||||
class async_result
|
||||
{
|
||||
BOOST_STATIC_ASSERT(
|
||||
! std::is_reference<CompletionToken>::value);
|
||||
|
||||
boost::asio::async_result<typename
|
||||
boost::asio::handler_type<CompletionToken,
|
||||
Signature>::type> impl_;
|
||||
|
||||
async_result(async_result const&) = delete;
|
||||
async_result& operator=(async_result const&) = delete;
|
||||
|
||||
public:
|
||||
/// The concrete completion handler type for the specific signature.
|
||||
using completion_handler_type =
|
||||
typename boost::asio::handler_type<
|
||||
CompletionToken, Signature>::type;
|
||||
|
||||
/// The return type of the initiating function.
|
||||
using return_type =
|
||||
typename boost::asio::async_result<
|
||||
completion_handler_type>::type;
|
||||
|
||||
/** Construct an async result from a given handler.
|
||||
|
||||
When using a specalised async_result, the constructor has
|
||||
an opportunity to initialise some state associated with the
|
||||
completion handler, which is then returned from the initiating
|
||||
function.
|
||||
*/
|
||||
explicit
|
||||
async_result(completion_handler_type& h)
|
||||
: impl_(h)
|
||||
{
|
||||
}
|
||||
|
||||
/// Obtain the value to be returned from the initiating function.
|
||||
return_type
|
||||
get()
|
||||
{
|
||||
return impl_.get();
|
||||
}
|
||||
};
|
||||
|
||||
/** Helper for customizing the return type of asynchronous initiation functions.
|
||||
|
||||
This class template is used to transform caller-provided completion
|
||||
handlers in calls to asynchronous initiation functions. The transformation
|
||||
allows customization of the return type of the initiating function, and the
|
||||
function signature of the final handler.
|
||||
|
||||
Example:
|
||||
@code
|
||||
...
|
||||
template<class CompletionToken>
|
||||
typename async_completion<CompletionToken, void(error_code)>::result_type
|
||||
async_initfn(..., CompletionToken&& handler)
|
||||
{
|
||||
async_completion<CompletionToken, void(error_code)> completion{handler};
|
||||
...
|
||||
return completion.result.get();
|
||||
}
|
||||
@endcode
|
||||
|
||||
@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.
|
||||
|
||||
@note See <a href="http://cplusplus.github.io/networking-ts/draft.pdf">
|
||||
Working Draft, C++ Extensions for Networking</a>
|
||||
|
||||
@see @ref async_return_type, @ref handler_type
|
||||
*/
|
||||
template<class CompletionToken, class Signature>
|
||||
struct async_completion
|
||||
{
|
||||
/** The type of the final handler called by the asynchronous initiation function.
|
||||
|
||||
Objects of this type will be callable with the specified signature.
|
||||
*/
|
||||
using completion_handler_type = typename async_result<
|
||||
typename std::decay<CompletionToken>::type,
|
||||
Signature>::completion_handler_type;
|
||||
|
||||
/** Constructor
|
||||
|
||||
The constructor creates the concrete completion handler and
|
||||
makes the link between the handler and the asynchronous
|
||||
result.
|
||||
|
||||
@param token The completion token. If this is a regular completion
|
||||
handler, copies may be made as needed. If the handler is movable,
|
||||
it may also be moved.
|
||||
*/
|
||||
explicit
|
||||
async_completion(CompletionToken& token)
|
||||
: completion_handler(static_cast<typename std::conditional<
|
||||
std::is_same<CompletionToken, completion_handler_type>::value,
|
||||
completion_handler_type&, CompletionToken&&>::type>(token))
|
||||
, result(completion_handler)
|
||||
{
|
||||
// CompletionToken is not invokable with the given signature
|
||||
static_assert(is_completion_handler<
|
||||
completion_handler_type, Signature>::value,
|
||||
"CompletionToken requirements not met: signature mismatch");
|
||||
}
|
||||
|
||||
/// The final completion handler, callable with the specified signature.
|
||||
typename std::conditional<std::is_same<
|
||||
CompletionToken, completion_handler_type>::value,
|
||||
completion_handler_type&,
|
||||
completion_handler_type
|
||||
>::type completion_handler;
|
||||
|
||||
/// The return value of the asynchronous initiation function.
|
||||
async_result<typename std::decay<
|
||||
CompletionToken>::type, Signature> result;
|
||||
};
|
||||
|
||||
template<class CompletionToken, typename Signature>
|
||||
using handler_type = typename beast::async_result<
|
||||
typename std::decay<CompletionToken>::type,
|
||||
Signature>::completion_handler_type;
|
||||
|
||||
template<class CompletionToken, typename Signature>
|
||||
using async_return_type = typename beast::async_result<
|
||||
typename std::decay<CompletionToken>::type,
|
||||
Signature>::return_type;
|
||||
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
@ -27,12 +27,12 @@ namespace beast {
|
||||
placeholders present in the list of bound arguments. Parameters
|
||||
which are not matched to placeholders are silently discarded.
|
||||
The passed handler and arguments are forwarded into the returned
|
||||
handler, which provides the same `io_service` execution guarantees
|
||||
handler, which provides the same `io_context` execution guarantees
|
||||
as the original handler.
|
||||
|
||||
Unlike `boost::asio::io_service::wrap`, the returned handler can
|
||||
be used in a subsequent call to `boost::asio::io_service::post`
|
||||
instead of `boost::asio::io_service::dispatch`, to ensure that
|
||||
Unlike `boost::asio::io_context::wrap`, the returned handler can
|
||||
be used in a subsequent call to `boost::asio::io_context::post`
|
||||
instead of `boost::asio::io_context::dispatch`, to ensure that
|
||||
the handler will not be invoked immediately by the calling
|
||||
function.
|
||||
|
||||
@ -43,7 +43,8 @@ namespace beast {
|
||||
void
|
||||
signal_aborted(AsyncReadStream& stream, ReadHandler&& handler)
|
||||
{
|
||||
stream.get_io_service().post(
|
||||
boost::asio::post(
|
||||
stream.get_executor(),
|
||||
bind_handler(std::forward<ReadHandler>(handler),
|
||||
boost::asio::error::operation_aborted, 0));
|
||||
}
|
||||
|
@ -11,12 +11,12 @@
|
||||
#define BOOST_BEAST_BUFFERED_READ_STREAM_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/beast/core/async_result.hpp>
|
||||
#include <boost/beast/core/error.hpp>
|
||||
#include <boost/beast/core/multi_buffer.hpp>
|
||||
#include <boost/beast/core/type_traits.hpp>
|
||||
#include <boost/asio/async_result.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
@ -91,7 +91,8 @@ namespace beast {
|
||||
template<class Stream, class DynamicBuffer>
|
||||
class buffered_read_stream
|
||||
{
|
||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||
static_assert(
|
||||
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||
"DynamicBuffer requirements not met");
|
||||
|
||||
template<class Buffers, class Handler>
|
||||
@ -163,11 +164,29 @@ public:
|
||||
return next_layer_.lowest_layer();
|
||||
}
|
||||
|
||||
/// Get the io_service associated with the object.
|
||||
boost::asio::io_service&
|
||||
get_io_service()
|
||||
/** Get the executor associated with the object.
|
||||
|
||||
This function may be used to obtain the executor object that the stream
|
||||
uses to dispatch handlers for asynchronous operations.
|
||||
|
||||
@return A copy of the executor that stream will use to dispatch handlers.
|
||||
|
||||
@note This function participates in overload resolution only if
|
||||
`NextLayer` has a member function named `get_executor`.
|
||||
*/
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
implementation_defined
|
||||
#else
|
||||
template<
|
||||
class T = next_layer_type,
|
||||
class = typename std::enable_if<
|
||||
has_get_executor<next_layer_type>::value>::type>
|
||||
auto
|
||||
#endif
|
||||
get_executor() noexcept ->
|
||||
decltype(std::declval<T&>().get_executor())
|
||||
{
|
||||
return next_layer_.get_io_service();
|
||||
return next_layer_.get_executor();
|
||||
}
|
||||
|
||||
/** Access the internal buffer.
|
||||
@ -265,14 +284,11 @@ public:
|
||||
Regardless of whether the asynchronous operation completes
|
||||
immediately or not, the handler will not be invoked from within
|
||||
this function. Invocation of the handler will be performed in a
|
||||
manner equivalent to using `boost::asio::io_service::post`.
|
||||
manner equivalent to using `boost::asio::io_context::post`.
|
||||
*/
|
||||
template<class MutableBufferSequence, class ReadHandler>
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
void_or_deduced
|
||||
#else
|
||||
async_return_type<ReadHandler, void(error_code)>
|
||||
#endif
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||
ReadHandler, void(error_code))
|
||||
async_read_some(MutableBufferSequence const& buffers,
|
||||
ReadHandler&& handler);
|
||||
|
||||
@ -340,14 +356,11 @@ public:
|
||||
Regardless of whether the asynchronous operation completes
|
||||
immediately or not, the handler will not be invoked from within
|
||||
this function. Invocation of the handler will be performed in a
|
||||
manner equivalent to using `boost::asio::io_service::post`.
|
||||
manner equivalent to using `boost::asio::io_context::post`.
|
||||
*/
|
||||
template<class ConstBufferSequence, class WriteHandler>
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
void_or_deduced
|
||||
#else
|
||||
async_return_type<WriteHandler, void(error_code)>
|
||||
#endif
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||
WriteHandler, void(error_code))
|
||||
async_write_some(ConstBufferSequence const& buffers,
|
||||
WriteHandler&& handler);
|
||||
};
|
||||
|
@ -35,10 +35,12 @@ namespace beast {
|
||||
template<class MutableBufferSequence>
|
||||
class buffers_adapter
|
||||
{
|
||||
static_assert(is_mutable_buffer_sequence<MutableBufferSequence>::value,
|
||||
static_assert(boost::asio::is_mutable_buffer_sequence<MutableBufferSequence>::value,
|
||||
"MutableBufferSequence requirements not met");
|
||||
|
||||
using iter_type = typename MutableBufferSequence::const_iterator;
|
||||
using iter_type = typename
|
||||
detail::buffer_sequence_iterator<
|
||||
MutableBufferSequence>::type;
|
||||
|
||||
MutableBufferSequence bs_;
|
||||
iter_type begin_;
|
||||
|
@ -34,8 +34,8 @@ class buffers_prefix_view
|
||||
using buffers_type = typename
|
||||
std::decay<BufferSequence>::type;
|
||||
|
||||
using iter_type =
|
||||
typename buffers_type::const_iterator;
|
||||
using iter_type = typename
|
||||
detail::buffer_sequence_iterator<buffers_type>::type;
|
||||
|
||||
BufferSequence bs_;
|
||||
std::size_t size_;
|
||||
@ -141,10 +141,8 @@ boost::asio::const_buffer
|
||||
buffers_prefix(std::size_t size,
|
||||
boost::asio::const_buffer buffer)
|
||||
{
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
return { buffer_cast<void const*>(buffer),
|
||||
(std::min)(size, buffer_size(buffer)) };
|
||||
return {buffer.data(),
|
||||
(std::min)(size, buffer.size())};
|
||||
}
|
||||
|
||||
/** Returns a prefix of a mutable buffer.
|
||||
@ -166,10 +164,8 @@ boost::asio::mutable_buffer
|
||||
buffers_prefix(std::size_t size,
|
||||
boost::asio::mutable_buffer buffer)
|
||||
{
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
return {buffer_cast<void*>(buffer),
|
||||
(std::min)(size, buffer_size(buffer))};
|
||||
return {buffer.data(),
|
||||
(std::min)(size, buffer.size())};
|
||||
}
|
||||
|
||||
/** Returns a prefix of a buffer sequence.
|
||||
@ -203,8 +199,8 @@ typename std::enable_if<
|
||||
buffers_prefix(std::size_t size, BufferSequence const& buffers)
|
||||
{
|
||||
static_assert(
|
||||
is_const_buffer_sequence<BufferSequence>::value ||
|
||||
is_mutable_buffer_sequence<BufferSequence>::value,
|
||||
boost::asio::is_const_buffer_sequence<BufferSequence>::value ||
|
||||
boost::asio::is_mutable_buffer_sequence<BufferSequence>::value,
|
||||
"BufferSequence requirements not met");
|
||||
return buffers_prefix_view<BufferSequence>(size, buffers);
|
||||
}
|
||||
@ -221,13 +217,14 @@ buffers_prefix(std::size_t size, BufferSequence const& buffers)
|
||||
*/
|
||||
template<class BufferSequence>
|
||||
typename std::conditional<
|
||||
is_mutable_buffer_sequence<BufferSequence>::value,
|
||||
boost::asio::is_mutable_buffer_sequence<BufferSequence>::value,
|
||||
boost::asio::mutable_buffer,
|
||||
boost::asio::const_buffer>::type
|
||||
buffers_front(BufferSequence const& buffers)
|
||||
{
|
||||
auto const first = buffers.begin();
|
||||
if(first == buffers.end())
|
||||
auto const first =
|
||||
boost::asio::buffer_sequence_begin(buffers);
|
||||
if(first == boost::asio::buffer_sequence_end(buffers))
|
||||
return {};
|
||||
return *first;
|
||||
}
|
||||
|
@ -12,11 +12,11 @@
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/beast/core/detail/in_place_init.hpp>
|
||||
#include <boost/beast/core/detail/type_traits.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
@ -57,8 +57,8 @@ class buffers_suffix
|
||||
using buffers_type =
|
||||
typename std::decay<BufferSequence>::type;
|
||||
|
||||
using iter_type =
|
||||
typename buffers_type::const_iterator;
|
||||
using iter_type = typename
|
||||
detail::buffer_sequence_iterator<buffers_type>::type;
|
||||
|
||||
BufferSequence bs_;
|
||||
iter_type begin_;
|
||||
@ -67,7 +67,9 @@ class buffers_suffix
|
||||
template<class Deduced>
|
||||
buffers_suffix(Deduced&& other, std::size_t dist)
|
||||
: bs_(std::forward<Deduced>(other).bs_)
|
||||
, begin_(std::next(bs_.begin(), dist))
|
||||
, begin_(std::next(
|
||||
boost::asio::buffer_sequence_begin(bs_),
|
||||
dist))
|
||||
, skip_(other.skip_)
|
||||
{
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
#define BOOST_BEAST_BUFFERS_TO_STRING_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/beast/core/detail/type_traits.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <string>
|
||||
|
||||
@ -45,10 +46,10 @@ buffers_to_string(ConstBufferSequence const& buffers)
|
||||
{
|
||||
std::string result;
|
||||
result.reserve(boost::asio::buffer_size(buffers));
|
||||
for(boost::asio::const_buffer buffer : buffers)
|
||||
result.append(
|
||||
boost::asio::buffer_cast<char const*>(buffer),
|
||||
boost::asio::buffer_size(buffer));
|
||||
for(boost::asio::const_buffer buffer :
|
||||
detail::buffers_range(buffers))
|
||||
result.append(reinterpret_cast<
|
||||
char const*>(buffer.data()), buffer.size());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -11,9 +11,9 @@
|
||||
#define BOOST_BEAST_DETAIL_BIND_HANDLER_HPP
|
||||
|
||||
#include <boost/beast/core/detail/integer_sequence.hpp>
|
||||
#include <boost/asio/handler_alloc_hook.hpp>
|
||||
#include <boost/asio/associated_allocator.hpp>
|
||||
#include <boost/asio/associated_executor.hpp>
|
||||
#include <boost/asio/handler_continuation_hook.hpp>
|
||||
#include <boost/asio/handler_invoke_hook.hpp>
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
@ -24,13 +24,17 @@ namespace detail {
|
||||
|
||||
/* Nullary handler that calls Handler with bound arguments.
|
||||
|
||||
The bound handler provides the same io_service execution
|
||||
The bound handler provides the same io_context execution
|
||||
guarantees as the original handler.
|
||||
*/
|
||||
template<class Handler, class... Args>
|
||||
class bound_handler
|
||||
{
|
||||
private:
|
||||
// Can't friend partial specializations,
|
||||
// so we just friend the whole thing.
|
||||
template<class T, class Executor>
|
||||
friend struct boost::asio::associated_executor;
|
||||
|
||||
using args_type = std::tuple<
|
||||
typename std::decay<Args>::type...>;
|
||||
|
||||
@ -101,6 +105,9 @@ private:
|
||||
public:
|
||||
using result_type = void;
|
||||
|
||||
using allocator_type =
|
||||
boost::asio::associated_allocator_t<Handler>;
|
||||
|
||||
bound_handler(bound_handler&&) = default;
|
||||
bound_handler(bound_handler const&) = default;
|
||||
|
||||
@ -113,6 +120,20 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
allocator_type
|
||||
get_allocator() const noexcept
|
||||
{
|
||||
return boost::asio::get_associated_allocator(h_);
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
asio_handler_is_continuation(bound_handler* h)
|
||||
{
|
||||
using boost::asio::asio_handler_is_continuation;
|
||||
return asio_handler_is_continuation(std::addressof(h->h_));
|
||||
}
|
||||
|
||||
template<class... Values>
|
||||
void
|
||||
operator()(Values&&... values)
|
||||
@ -132,48 +153,30 @@ public:
|
||||
std::forward<Values>(values)...),
|
||||
index_sequence_for<Args...>());
|
||||
}
|
||||
|
||||
friend
|
||||
void*
|
||||
asio_handler_allocate(
|
||||
std::size_t size, bound_handler* h)
|
||||
{
|
||||
using boost::asio::asio_handler_allocate;
|
||||
return asio_handler_allocate(
|
||||
size, std::addressof(h->h_));
|
||||
}
|
||||
|
||||
friend
|
||||
void
|
||||
asio_handler_deallocate(
|
||||
void* p, std::size_t size, bound_handler* h)
|
||||
{
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
asio_handler_deallocate(
|
||||
p, size, std::addressof(h->h_));
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
asio_handler_is_continuation(bound_handler* h)
|
||||
{
|
||||
using boost::asio::asio_handler_is_continuation;
|
||||
return asio_handler_is_continuation(std::addressof(h->h_));
|
||||
}
|
||||
|
||||
template<class F>
|
||||
friend
|
||||
void
|
||||
asio_handler_invoke(F&& f, bound_handler* h)
|
||||
{
|
||||
using boost::asio::asio_handler_invoke;
|
||||
asio_handler_invoke(
|
||||
f, std::addressof(h->h_));
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // beast
|
||||
|
||||
namespace asio {
|
||||
template<class Handler, class... Args, class Executor>
|
||||
struct associated_executor<
|
||||
beast::detail::bound_handler<Handler, Args...>, Executor>
|
||||
{
|
||||
using type = typename
|
||||
associated_executor<Handler, Executor>::type;
|
||||
|
||||
static
|
||||
type
|
||||
get(beast::detail::bound_handler<Handler, Args...> const& h,
|
||||
Executor const& ex = Executor()) noexcept
|
||||
{
|
||||
return associated_executor<
|
||||
Handler, Executor>::get(h.h_, ex);
|
||||
}
|
||||
};
|
||||
} // asio
|
||||
|
||||
} // boost
|
||||
|
||||
namespace std {
|
||||
|
@ -11,6 +11,7 @@
|
||||
#define BOOST_BEAST_DETAIL_BUFFERS_REF_HPP
|
||||
|
||||
#include <boost/beast/core/type_traits.hpp>
|
||||
#include <iterator>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
@ -23,11 +24,11 @@ class buffers_ref
|
||||
BufferSequence const* buffers_;
|
||||
|
||||
public:
|
||||
using value_type =
|
||||
typename BufferSequence::value_type;
|
||||
using const_iterator = typename
|
||||
buffer_sequence_iterator<BufferSequence>::type;
|
||||
|
||||
using const_iterator =
|
||||
typename BufferSequence::const_iterator;
|
||||
using value_type = typename std::iterator_traits<
|
||||
const_iterator>::value_type;
|
||||
|
||||
buffers_ref(buffers_ref const&) = default;
|
||||
buffers_ref& operator=(buffers_ref const&) = default;
|
||||
@ -41,13 +42,13 @@ public:
|
||||
const_iterator
|
||||
begin() const
|
||||
{
|
||||
return buffers_->begin();
|
||||
return boost::asio::buffer_sequence_begin(*buffers_);
|
||||
}
|
||||
|
||||
const_iterator
|
||||
end() const
|
||||
{
|
||||
return buffers_->end();
|
||||
return boost::asio::buffer_sequence_end(*buffers_);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -10,8 +10,10 @@
|
||||
#ifndef BOOST_BEAST_DETAIL_OSTREAM_HPP
|
||||
#define BOOST_BEAST_DETAIL_OSTREAM_HPP
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/beast/core/buffers_prefix.hpp>
|
||||
#include <boost/beast/core/read_size.hpp>
|
||||
#include <boost/beast/core/detail/type_traits.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <memory>
|
||||
#include <iosfwd>
|
||||
#include <streambuf>
|
||||
@ -46,11 +48,10 @@ std::ostream&
|
||||
operator<<(std::ostream& os,
|
||||
buffers_helper<Buffers> const& v)
|
||||
{
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
for(boost::asio::const_buffer b : v.b_)
|
||||
os.write(buffer_cast<char const*>(b),
|
||||
buffer_size(b));
|
||||
for(auto b : buffers_range(v.b_))
|
||||
os.write(
|
||||
reinterpret_cast<char const*>(b.data()),
|
||||
b.size());
|
||||
return os;
|
||||
}
|
||||
|
||||
@ -130,14 +131,12 @@ private:
|
||||
void
|
||||
prepare()
|
||||
{
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
auto mbs = buf_.prepare(
|
||||
auto bs = buf_.prepare(
|
||||
read_size_or_throw(buf_, max_size));
|
||||
auto const mb = *mbs.begin();
|
||||
auto const p = buffer_cast<CharT*>(mb);
|
||||
auto const b = buffers_front(bs);
|
||||
auto const p = reinterpret_cast<CharT*>(b.data());
|
||||
this->setp(p,
|
||||
p + buffer_size(mb) / sizeof(CharT) - 1);
|
||||
p + b.size() / sizeof(CharT) - 1);
|
||||
}
|
||||
|
||||
void
|
||||
@ -211,14 +210,12 @@ private:
|
||||
void
|
||||
prepare()
|
||||
{
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
auto mbs = buf_.prepare(
|
||||
auto bs = buf_.prepare(
|
||||
read_size_or_throw(buf_, max_size));
|
||||
auto const mb = *mbs.begin();
|
||||
auto const p = buffer_cast<CharT*>(mb);
|
||||
auto const b = buffers_front(bs);
|
||||
auto const p = reinterpret_cast<CharT*>(b.data());
|
||||
this->setp(p,
|
||||
p + buffer_size(mb) / sizeof(CharT) - 1);
|
||||
p + b.size() / sizeof(CharT) - 1);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -12,38 +12,12 @@
|
||||
|
||||
#include <boost/beast/core/error.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <iterator>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
// A few workarounds to keep things working
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
|
||||
// for has_get_io_service
|
||||
class io_service;
|
||||
|
||||
// for is_dynamic_buffer
|
||||
template<class Allocator>
|
||||
class basic_streambuf;
|
||||
|
||||
namespace detail {
|
||||
|
||||
// for is_buffer_sequence
|
||||
template<class Buffer, class Buffers>
|
||||
class consuming_buffers;
|
||||
|
||||
} // detail
|
||||
|
||||
} // asio
|
||||
} // boost
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace detail {
|
||||
@ -281,57 +255,17 @@ using ConstBufferSequence =
|
||||
using MutableBufferSequence =
|
||||
BufferSequence<boost::asio::mutable_buffer>;
|
||||
|
||||
template<class T, class B, class = void>
|
||||
struct is_buffer_sequence : std::false_type {};
|
||||
|
||||
template<class T, class B>
|
||||
struct is_buffer_sequence<T, B, void_t<decltype(
|
||||
std::declval<typename T::value_type>(),
|
||||
std::declval<typename T::const_iterator&>() =
|
||||
std::declval<T const&>().begin(),
|
||||
std::declval<typename T::const_iterator&>() =
|
||||
std::declval<T const&>().end(),
|
||||
(void)0)>> : std::integral_constant<bool,
|
||||
std::is_convertible<typename T::value_type, B>::value &&
|
||||
#if 0
|
||||
std::is_base_of<std::bidirectional_iterator_tag,
|
||||
typename std::iterator_traits<
|
||||
typename T::const_iterator>::iterator_category>::value
|
||||
#else
|
||||
// workaround:
|
||||
// boost::asio::detail::consuming_buffers::const_iterator
|
||||
// is not bidirectional
|
||||
std::is_base_of<std::forward_iterator_tag,
|
||||
typename std::iterator_traits<
|
||||
typename T::const_iterator>::iterator_category>::value
|
||||
#endif
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
#if 0
|
||||
// workaround:
|
||||
// boost::asio::detail::consuming_buffers::const_iterator
|
||||
// is not bidirectional
|
||||
template<class Buffer, class Buffers, class B>
|
||||
struct is_buffer_sequence<
|
||||
boost::asio::detail::consuming_buffers<Buffer, Buffers>>
|
||||
: std::true_type
|
||||
{
|
||||
};
|
||||
#endif
|
||||
|
||||
template<class B1, class... Bn>
|
||||
struct is_all_const_buffer_sequence
|
||||
: std::integral_constant<bool,
|
||||
is_buffer_sequence<B1, boost::asio::const_buffer>::value &&
|
||||
boost::asio::is_const_buffer_sequence<B1>::value &&
|
||||
is_all_const_buffer_sequence<Bn...>::value>
|
||||
{
|
||||
};
|
||||
|
||||
template<class B1>
|
||||
struct is_all_const_buffer_sequence<B1>
|
||||
: is_buffer_sequence<B1, boost::asio::const_buffer>
|
||||
template<class B>
|
||||
struct is_all_const_buffer_sequence<B>
|
||||
: boost::asio::is_const_buffer_sequence<B>
|
||||
{
|
||||
};
|
||||
|
||||
@ -346,6 +280,14 @@ struct common_buffers_type
|
||||
boost::asio::const_buffer>::type;
|
||||
};
|
||||
|
||||
template<class B>
|
||||
struct buffer_sequence_iterator
|
||||
{
|
||||
using type = decltype(
|
||||
boost::asio::buffer_sequence_begin(
|
||||
std::declval<B const&>()));
|
||||
};
|
||||
|
||||
// Types that meet the requirements,
|
||||
// for use with std::declval only.
|
||||
struct StreamHandler
|
||||
@ -356,6 +298,54 @@ struct StreamHandler
|
||||
using ReadHandler = StreamHandler;
|
||||
using WriteHandler = StreamHandler;
|
||||
|
||||
template<class Buffers>
|
||||
class buffers_range_adapter
|
||||
{
|
||||
Buffers const& b_;
|
||||
|
||||
public:
|
||||
using value_type = typename std::conditional<
|
||||
std::is_convertible<typename std::iterator_traits<
|
||||
typename buffer_sequence_iterator<Buffers>::type>::value_type,
|
||||
boost::asio::const_buffer>::value,
|
||||
boost::asio::const_buffer,
|
||||
boost::asio::mutable_buffer>::type;
|
||||
|
||||
/* VFALCO This isn't right, because range-for will pick up the iterator's
|
||||
value_type which might not be const_buffer or mutable_buffer. We
|
||||
need to declare our own iterator wrapper that converts the underlying
|
||||
iterator's value_type to const_buffer or mutable_buffer so that
|
||||
range-for sees one of those types.
|
||||
*/
|
||||
using const_iterator = typename
|
||||
buffer_sequence_iterator<Buffers>::type;
|
||||
|
||||
explicit
|
||||
buffers_range_adapter(Buffers const& b)
|
||||
: b_(b)
|
||||
{
|
||||
}
|
||||
|
||||
const_iterator
|
||||
begin() const noexcept
|
||||
{
|
||||
return boost::asio::buffer_sequence_begin(b_);
|
||||
}
|
||||
|
||||
const_iterator
|
||||
end() const noexcept
|
||||
{
|
||||
return boost::asio::buffer_sequence_end(b_);
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffers>
|
||||
buffers_range_adapter<Buffers>
|
||||
buffers_range(Buffers const& buffers)
|
||||
{
|
||||
return buffers_range_adapter<Buffers>{buffers};
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // beast
|
||||
} // boost
|
||||
|
@ -84,10 +84,10 @@ public:
|
||||
using allocator_type = Allocator;
|
||||
|
||||
/// The type used to represent the input sequence as a list of buffers.
|
||||
using const_buffers_type = boost::asio::mutable_buffers_1;
|
||||
using const_buffers_type = boost::asio::mutable_buffer;
|
||||
|
||||
/// The type used to represent the output sequence as a list of buffers.
|
||||
using mutable_buffers_type = boost::asio::mutable_buffers_1;
|
||||
using mutable_buffers_type = boost::asio::mutable_buffer;
|
||||
|
||||
/// Destructor
|
||||
~basic_flat_buffer();
|
||||
|
@ -52,13 +52,13 @@ public:
|
||||
|
||||
This buffer sequence is guaranteed to have length 1.
|
||||
*/
|
||||
using const_buffers_type = boost::asio::mutable_buffers_1;
|
||||
using const_buffers_type = boost::asio::mutable_buffer;
|
||||
|
||||
/** The type used to represent the output sequence as a list of buffers.
|
||||
|
||||
This buffer sequence is guaranteed to have length 1.
|
||||
*/
|
||||
using mutable_buffers_type = boost::asio::mutable_buffers_1;
|
||||
using mutable_buffers_type = boost::asio::mutable_buffer;
|
||||
|
||||
/** Constructor
|
||||
|
||||
|
@ -1,162 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2016-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)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/beast
|
||||
//
|
||||
|
||||
#ifndef BOOST_BEAST_HANDLER_ALLOC_HPP
|
||||
#define BOOST_BEAST_HANDLER_ALLOC_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/asio/handler_alloc_hook.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
|
||||
// Guidance from
|
||||
// http://howardhinnant.github.io/allocator_boilerplate.html
|
||||
|
||||
/** An allocator that uses handler customizations.
|
||||
|
||||
This allocator uses the handler customizations `asio_handler_allocate`
|
||||
and `asio_handler_deallocate` to manage memory. It meets the requirements
|
||||
of @b Allocator and can be used anywhere a `std::allocator` is
|
||||
accepted.
|
||||
|
||||
@tparam T The type of objects allocated by the allocator.
|
||||
|
||||
@tparam Handler The type of handler.
|
||||
|
||||
@note Memory allocated by this allocator must be freed before
|
||||
the handler is invoked or undefined behavior results. This behavior
|
||||
is described as the "deallocate before invocation" Asio guarantee.
|
||||
*/
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
template<class T, class Handler>
|
||||
class handler_alloc;
|
||||
#else
|
||||
template<class T, class Handler>
|
||||
class handler_alloc
|
||||
{
|
||||
private:
|
||||
// We want a partial template specialization as a friend
|
||||
// but that isn't allowed so we friend all versions. This
|
||||
// should produce a compile error if Handler is not
|
||||
// constructible from H.
|
||||
//
|
||||
template<class U, class H>
|
||||
friend class handler_alloc;
|
||||
|
||||
Handler& h_;
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
using is_always_equal = std::true_type;
|
||||
using pointer = T*;
|
||||
using reference = T&;
|
||||
using const_pointer = T const*;
|
||||
using const_reference = T const&;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
template<class U>
|
||||
struct rebind
|
||||
{
|
||||
using other = handler_alloc<U, Handler>;
|
||||
};
|
||||
|
||||
handler_alloc() = delete;
|
||||
handler_alloc(handler_alloc&&) = default;
|
||||
handler_alloc(handler_alloc const&) = default;
|
||||
handler_alloc& operator=(handler_alloc&&) = default;
|
||||
handler_alloc& operator=(handler_alloc const&) = default;
|
||||
|
||||
/** Construct the allocator.
|
||||
|
||||
A reference of the handler is stored. The handler must
|
||||
remain valid for at least the lifetime of the allocator.
|
||||
*/
|
||||
explicit
|
||||
handler_alloc(Handler& h)
|
||||
: h_(h)
|
||||
{
|
||||
}
|
||||
|
||||
/// Copy constructor
|
||||
template<class U>
|
||||
handler_alloc(
|
||||
handler_alloc<U, Handler> const& other)
|
||||
: h_(other.h_)
|
||||
{
|
||||
}
|
||||
|
||||
value_type*
|
||||
allocate(size_type n)
|
||||
{
|
||||
auto const size = n * sizeof(T);
|
||||
using boost::asio::asio_handler_allocate;
|
||||
return static_cast<value_type*>(
|
||||
asio_handler_allocate(size, std::addressof(h_)));
|
||||
}
|
||||
|
||||
void
|
||||
deallocate(value_type* p, size_type n)
|
||||
{
|
||||
auto const size = n * sizeof(T);
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
asio_handler_deallocate(p, size, std::addressof(h_));
|
||||
}
|
||||
|
||||
//#if BOOST_WORKAROUND(BOOST_GCC, < 60000) // Works, but too coarse
|
||||
|
||||
#if defined(BOOST_LIBSTDCXX_VERSION) && BOOST_LIBSTDCXX_VERSION < 60000
|
||||
template<class U, class... Args>
|
||||
void
|
||||
construct(U* ptr, Args&&... args)
|
||||
{
|
||||
::new((void*)ptr) U(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<class U>
|
||||
void
|
||||
destroy(U* ptr)
|
||||
{
|
||||
ptr->~U();
|
||||
}
|
||||
#endif
|
||||
|
||||
template<class U>
|
||||
friend
|
||||
bool
|
||||
operator==(
|
||||
handler_alloc const&,
|
||||
handler_alloc<U, Handler> const&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class U>
|
||||
friend
|
||||
bool
|
||||
operator!=(
|
||||
handler_alloc const& lhs,
|
||||
handler_alloc<U, Handler> const& rhs)
|
||||
{
|
||||
return ! (lhs == rhs);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
@ -16,9 +16,10 @@
|
||||
#include <boost/beast/core/read_size.hpp>
|
||||
#include <boost/beast/core/type_traits.hpp>
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/asio/handler_alloc_hook.hpp>
|
||||
#include <boost/asio/associated_allocator.hpp>
|
||||
#include <boost/asio/associated_executor.hpp>
|
||||
#include <boost/asio/handler_continuation_hook.hpp>
|
||||
#include <boost/asio/handler_invoke_hook.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
namespace boost {
|
||||
@ -48,28 +49,28 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
using allocator_type =
|
||||
boost::asio::associated_allocator_t<Handler>;
|
||||
|
||||
allocator_type
|
||||
get_allocator() const noexcept
|
||||
{
|
||||
return boost::asio::get_associated_allocator(h_);
|
||||
}
|
||||
|
||||
using executor_type = boost::asio::associated_executor_t<
|
||||
Handler, decltype(s_.get_executor())>;
|
||||
|
||||
executor_type get_executor() const noexcept
|
||||
{
|
||||
return boost::asio::get_associated_executor(
|
||||
h_, s_.get_executor());
|
||||
}
|
||||
|
||||
void
|
||||
operator()(error_code const& ec,
|
||||
std::size_t bytes_transferred);
|
||||
|
||||
friend
|
||||
void* asio_handler_allocate(
|
||||
std::size_t size, read_some_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_allocate;
|
||||
return asio_handler_allocate(
|
||||
size, std::addressof(op->h_));
|
||||
}
|
||||
|
||||
friend
|
||||
void asio_handler_deallocate(
|
||||
void* p, std::size_t size, read_some_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
asio_handler_deallocate(
|
||||
p, size, std::addressof(op->h_));
|
||||
}
|
||||
|
||||
friend
|
||||
bool asio_handler_is_continuation(read_some_op* op)
|
||||
{
|
||||
@ -77,14 +78,6 @@ public:
|
||||
return asio_handler_is_continuation(
|
||||
std::addressof(op->h_));
|
||||
}
|
||||
|
||||
template<class Function>
|
||||
friend
|
||||
void asio_handler_invoke(Function&& f, read_some_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_invoke;
|
||||
asio_handler_invoke(f, std::addressof(op->h_));
|
||||
}
|
||||
};
|
||||
|
||||
template<class Stream, class DynamicBuffer>
|
||||
@ -116,9 +109,9 @@ read_some_op<MutableBufferSequence, Handler>::operator()(
|
||||
|
||||
}
|
||||
step_ = 3;
|
||||
s_.get_io_service().post(
|
||||
return boost::asio::post(
|
||||
s_.get_executor(),
|
||||
bind_handler(std::move(*this), ec, 0));
|
||||
return;
|
||||
|
||||
case 1:
|
||||
// upcall
|
||||
@ -153,11 +146,11 @@ auto
|
||||
buffered_read_stream<Stream, DynamicBuffer>::
|
||||
async_write_some(ConstBufferSequence const& buffers,
|
||||
WriteHandler&& handler) ->
|
||||
async_return_type<WriteHandler, void(error_code)>
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void(error_code))
|
||||
{
|
||||
static_assert(is_async_write_stream<next_layer_type>::value,
|
||||
"AsyncWriteStream requirements not met");
|
||||
static_assert(is_const_buffer_sequence<
|
||||
static_assert(boost::asio::is_const_buffer_sequence<
|
||||
ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
static_assert(is_completion_handler<WriteHandler,
|
||||
@ -176,7 +169,7 @@ read_some(
|
||||
{
|
||||
static_assert(is_sync_read_stream<next_layer_type>::value,
|
||||
"SyncReadStream requirements not met");
|
||||
static_assert(is_mutable_buffer_sequence<
|
||||
static_assert(boost::asio::is_mutable_buffer_sequence<
|
||||
MutableBufferSequence>::value,
|
||||
"MutableBufferSequence requirements not met");
|
||||
error_code ec;
|
||||
@ -195,7 +188,7 @@ read_some(MutableBufferSequence const& buffers,
|
||||
{
|
||||
static_assert(is_sync_read_stream<next_layer_type>::value,
|
||||
"SyncReadStream requirements not met");
|
||||
static_assert(is_mutable_buffer_sequence<
|
||||
static_assert(boost::asio::is_mutable_buffer_sequence<
|
||||
MutableBufferSequence>::value,
|
||||
"MutableBufferSequence requirements not met");
|
||||
using boost::asio::buffer_size;
|
||||
@ -226,20 +219,20 @@ auto
|
||||
buffered_read_stream<Stream, DynamicBuffer>::
|
||||
async_read_some(MutableBufferSequence const& buffers,
|
||||
ReadHandler&& handler) ->
|
||||
async_return_type<ReadHandler, void(error_code)>
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void(error_code))
|
||||
{
|
||||
static_assert(is_async_read_stream<next_layer_type>::value,
|
||||
"Stream requirements not met");
|
||||
static_assert(is_mutable_buffer_sequence<
|
||||
"AsyncReadStream requirements not met");
|
||||
static_assert(boost::asio::is_mutable_buffer_sequence<
|
||||
MutableBufferSequence>::value,
|
||||
"MutableBufferSequence requirements not met");
|
||||
if(buffer_.size() == 0 && capacity_ == 0)
|
||||
return next_layer_.async_read_some(buffers,
|
||||
std::forward<ReadHandler>(handler));
|
||||
async_completion<ReadHandler,
|
||||
boost::asio::async_completion<ReadHandler,
|
||||
void(error_code, std::size_t)> init{handler};
|
||||
read_some_op<MutableBufferSequence, handler_type<
|
||||
ReadHandler, void(error_code, std::size_t)>>{
|
||||
read_some_op<MutableBufferSequence, BOOST_ASIO_HANDLER_TYPE(
|
||||
ReadHandler, void(error_code, std::size_t))>{
|
||||
init.completion_handler, *this, buffers}(
|
||||
error_code{}, 0);
|
||||
return init.result.get();
|
||||
|
@ -90,11 +90,10 @@ public:
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
return value_type{buffer_cast<void const*>(*it_),
|
||||
(ba_->out_ == ba_->bs_.end() ||
|
||||
it_ != ba_->out_) ? buffer_size(*it_) : ba_->out_pos_} +
|
||||
value_type const b = *it_;
|
||||
return value_type{b.data(),
|
||||
(ba_->out_ == boost::asio::buffer_sequence_end(ba_->bs_) ||
|
||||
it_ != ba_->out_) ? b.size() : ba_->out_pos_} +
|
||||
(it_ == ba_->begin_ ? ba_->in_pos_ : 0);
|
||||
}
|
||||
|
||||
@ -233,11 +232,10 @@ public:
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
return value_type{buffer_cast<void*>(*it_),
|
||||
value_type const b = *it_;
|
||||
return value_type{b.data(),
|
||||
it_ == std::prev(ba_->end_) ?
|
||||
ba_->out_end_ : buffer_size(*it_)} +
|
||||
ba_->out_end_ : b.size()} +
|
||||
(it_ == ba_->out_ ? ba_->out_pos_ : 0);
|
||||
}
|
||||
|
||||
@ -288,7 +286,9 @@ private:
|
||||
template<class MutableBufferSequence>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<MutableBufferSequence>::mutable_buffers_type::begin() const ->
|
||||
buffers_adapter<MutableBufferSequence>::
|
||||
mutable_buffers_type::
|
||||
begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*ba_, ba_->out_};
|
||||
@ -297,7 +297,9 @@ buffers_adapter<MutableBufferSequence>::mutable_buffers_type::begin() const ->
|
||||
template<class MutableBufferSequence>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<MutableBufferSequence>::mutable_buffers_type::end() const ->
|
||||
buffers_adapter<MutableBufferSequence>::
|
||||
mutable_buffers_type::
|
||||
end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*ba_, ba_->end_};
|
||||
@ -309,9 +311,9 @@ template<class MutableBufferSequence>
|
||||
buffers_adapter<MutableBufferSequence>::buffers_adapter(
|
||||
buffers_adapter&& other)
|
||||
: buffers_adapter(std::move(other),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.begin_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.out_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.end_))
|
||||
std::distance<iter_type>(boost::asio::buffer_sequence_begin(other.bs_), other.begin_),
|
||||
std::distance<iter_type>(boost::asio::buffer_sequence_begin(other.bs_), other.out_),
|
||||
std::distance<iter_type>(boost::asio::buffer_sequence_begin(other.bs_), other.end_))
|
||||
{
|
||||
}
|
||||
|
||||
@ -319,9 +321,9 @@ template<class MutableBufferSequence>
|
||||
buffers_adapter<MutableBufferSequence>::buffers_adapter(
|
||||
buffers_adapter const& other)
|
||||
: buffers_adapter(other,
|
||||
std::distance<iter_type>(other.bs_.begin(), other.begin_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.out_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.end_))
|
||||
std::distance<iter_type>(boost::asio::buffer_sequence_begin(other.bs_), other.begin_),
|
||||
std::distance<iter_type>(boost::asio::buffer_sequence_begin(other.bs_), other.out_),
|
||||
std::distance<iter_type>(boost::asio::buffer_sequence_begin(other.bs_), other.end_))
|
||||
{
|
||||
}
|
||||
|
||||
@ -331,15 +333,18 @@ buffers_adapter<MutableBufferSequence>::operator=(
|
||||
buffers_adapter&& other) -> buffers_adapter&
|
||||
{
|
||||
auto const nbegin = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_);
|
||||
boost::asio::buffer_sequence_begin(other.bs_),
|
||||
other.begin_);
|
||||
auto const nout = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.out_);
|
||||
boost::asio::buffer_sequence_begin(other.bs_),
|
||||
other.out_);
|
||||
auto const nend = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.end_);
|
||||
boost::asio::buffer_sequence_begin(other.bs_),
|
||||
other.end_);
|
||||
bs_ = std::move(other.bs_);
|
||||
begin_ = std::next(bs_.begin(), nbegin);
|
||||
out_ = std::next(bs_.begin(), nout);
|
||||
end_ = std::next(bs_.begin(), nend);
|
||||
begin_ = std::next(boost::asio::buffer_sequence_begin(bs_), nbegin);
|
||||
out_ = std::next(boost::asio::buffer_sequence_begin(bs_), nout);
|
||||
end_ = std::next(boost::asio::buffer_sequence_begin(bs_), nend);
|
||||
max_size_ = other.max_size_;
|
||||
in_pos_ = other.in_pos_;
|
||||
in_size_ = other.in_size_;
|
||||
@ -354,15 +359,18 @@ buffers_adapter<MutableBufferSequence>::operator=(
|
||||
buffers_adapter const& other) -> buffers_adapter&
|
||||
{
|
||||
auto const nbegin = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_);
|
||||
boost::asio::buffer_sequence_begin(other.bs_),
|
||||
other.begin_);
|
||||
auto const nout = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.out_);
|
||||
boost::asio::buffer_sequence_begin(other.bs_),
|
||||
other.out_);
|
||||
auto const nend = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.end_);
|
||||
boost::asio::buffer_sequence_begin(other.bs_),
|
||||
other.end_);
|
||||
bs_ = other.bs_;
|
||||
begin_ = std::next(bs_.begin(), nbegin);
|
||||
out_ = std::next(bs_.begin(), nout);
|
||||
end_ = std::next(bs_.begin(), nend);
|
||||
begin_ = std::next(boost::asio::buffer_sequence_begin(bs_), nbegin);
|
||||
out_ = std::next(boost::asio::buffer_sequence_begin(bs_), nout);
|
||||
end_ = std::next(boost::asio::buffer_sequence_begin(bs_), nend);
|
||||
max_size_ = other.max_size_;
|
||||
in_pos_ = other.in_pos_;
|
||||
in_size_ = other.in_size_;
|
||||
@ -375,9 +383,9 @@ template<class MutableBufferSequence>
|
||||
buffers_adapter<MutableBufferSequence>::buffers_adapter(
|
||||
MutableBufferSequence const& bs)
|
||||
: bs_(bs)
|
||||
, begin_(bs_.begin())
|
||||
, out_(bs_.begin())
|
||||
, end_(bs_.begin())
|
||||
, begin_(boost::asio::buffer_sequence_begin(bs_))
|
||||
, out_ (boost::asio::buffer_sequence_begin(bs_))
|
||||
, end_ (boost::asio::buffer_sequence_begin(bs_))
|
||||
, max_size_(boost::asio::buffer_size(bs_))
|
||||
{
|
||||
}
|
||||
@ -389,13 +397,14 @@ buffers_adapter<MutableBufferSequence>::prepare(std::size_t n) ->
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
end_ = out_;
|
||||
if(end_ != bs_.end())
|
||||
if(end_ != boost::asio::buffer_sequence_end(bs_))
|
||||
{
|
||||
auto size = buffer_size(*end_) - out_pos_;
|
||||
if(n > size)
|
||||
{
|
||||
n -= size;
|
||||
while(++end_ != bs_.end())
|
||||
while(++end_ !=
|
||||
boost::asio::buffer_sequence_end(bs_))
|
||||
{
|
||||
size = buffer_size(*end_);
|
||||
if(n < size)
|
||||
|
@ -30,7 +30,7 @@ class buffers_cat_view<Bn...>::const_iterator
|
||||
std::size_t n_;
|
||||
std::tuple<Bn...> const* bn_;
|
||||
std::array<char, detail::max_sizeof<
|
||||
typename Bn::const_iterator...>()> buf_;
|
||||
typename detail::buffer_sequence_iterator<Bn>::type...>()> buf_;
|
||||
|
||||
friend class buffers_cat_view<Bn...>;
|
||||
|
||||
@ -38,8 +38,8 @@ class buffers_cat_view<Bn...>::const_iterator
|
||||
using C = std::integral_constant<std::size_t, I>;
|
||||
|
||||
template<std::size_t I>
|
||||
using iter_t = typename std::tuple_element<
|
||||
I, std::tuple<Bn...>>::type::const_iterator;
|
||||
using iter_t = typename detail::buffer_sequence_iterator<
|
||||
typename std::tuple_element<I, std::tuple<Bn...>>::type>::type;
|
||||
|
||||
template<std::size_t I>
|
||||
iter_t<I>&
|
||||
@ -123,7 +123,8 @@ private:
|
||||
{
|
||||
n_ = I;
|
||||
new(&buf_[0]) iter_t<I>{
|
||||
std::get<I>(*bn_).begin()};
|
||||
boost::asio::buffer_sequence_begin(
|
||||
std::get<I>(*bn_))};
|
||||
return;
|
||||
}
|
||||
construct(C<I+1>{});
|
||||
@ -138,7 +139,8 @@ private:
|
||||
{
|
||||
n_ = I;
|
||||
new(&buf_[0]) iter_t<I>{
|
||||
std::get<I>(*bn_).end()};
|
||||
boost::asio::buffer_sequence_end(
|
||||
std::get<I>(*bn_))};
|
||||
return;
|
||||
}
|
||||
BOOST_THROW_EXCEPTION(std::logic_error{
|
||||
@ -154,7 +156,8 @@ private:
|
||||
{
|
||||
n_ = I;
|
||||
new(&buf_[0]) iter_t<I>{
|
||||
std::get<I>(*bn_).end()};
|
||||
boost::asio::buffer_sequence_end(
|
||||
std::get<I>(*bn_))};
|
||||
return;
|
||||
}
|
||||
rconstruct(C<I-1>{});
|
||||
@ -268,7 +271,8 @@ private:
|
||||
if(n_ == I)
|
||||
{
|
||||
if(++iter<I>() !=
|
||||
std::get<I>(*bn_).end())
|
||||
boost::asio::buffer_sequence_end(
|
||||
std::get<I>(*bn_)))
|
||||
return;
|
||||
using Iter = iter_t<I>;
|
||||
iter<I>().~Iter();
|
||||
@ -292,7 +296,9 @@ private:
|
||||
{
|
||||
if(n_ == I)
|
||||
{
|
||||
if(iter<I>() != std::get<I>(*bn_).begin())
|
||||
if(iter<I>() !=
|
||||
boost::asio::buffer_sequence_begin(
|
||||
std::get<I>(*bn_)))
|
||||
{
|
||||
--iter<I>();
|
||||
return;
|
||||
@ -309,7 +315,9 @@ private:
|
||||
decrement(C<0> const&)
|
||||
{
|
||||
auto constexpr I = 0;
|
||||
if(iter<I>() != std::get<I>(*bn_).begin())
|
||||
if(iter<I>() !=
|
||||
boost::asio::buffer_sequence_begin(
|
||||
std::get<I>(*bn_)))
|
||||
{
|
||||
--iter<I>();
|
||||
return;
|
||||
|
@ -27,10 +27,8 @@ boost::asio::const_buffer
|
||||
buffers_prefix(std::size_t size,
|
||||
boost::asio::const_buffer buffer)
|
||||
{
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
return {buffer_cast<void const*>(buffer),
|
||||
(std::min)(size, buffer_size(buffer))};
|
||||
return {buffer.data(),
|
||||
(std::min)(size, buffer.size())};
|
||||
}
|
||||
|
||||
inline
|
||||
@ -38,10 +36,8 @@ boost::asio::mutable_buffer
|
||||
buffers_prefix(std::size_t size,
|
||||
boost::asio::mutable_buffer buffer)
|
||||
{
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
return {buffer_cast<void*>(buffer),
|
||||
(std::min)(size, buffer_size(buffer))};
|
||||
return {buffer.data(),
|
||||
(std::min)(size, buffer.size())};
|
||||
}
|
||||
|
||||
} // detail
|
||||
@ -138,7 +134,7 @@ private:
|
||||
std::false_type)
|
||||
: b_(&b)
|
||||
, remain_(b_->size_)
|
||||
, it_(b_->bs_.begin())
|
||||
, it_(boost::asio::buffer_sequence_begin(b_->bs_))
|
||||
{
|
||||
}
|
||||
};
|
||||
@ -149,7 +145,7 @@ buffers_prefix_view<BufferSequence>::
|
||||
setup(std::size_t size)
|
||||
{
|
||||
size_ = 0;
|
||||
end_ = bs_.begin();
|
||||
end_ = boost::asio::buffer_sequence_begin(bs_);
|
||||
auto const last = bs_.end();
|
||||
while(end_ != last)
|
||||
{
|
||||
@ -170,7 +166,8 @@ buffers_prefix_view<BufferSequence>::
|
||||
buffers_prefix_view(buffers_prefix_view&& other)
|
||||
: buffers_prefix_view(std::move(other),
|
||||
std::distance<iter_type>(
|
||||
other.bs_.begin(), other.end_))
|
||||
boost::asio::buffer_sequence_begin(other.bs_),
|
||||
other.end_))
|
||||
{
|
||||
}
|
||||
|
||||
@ -179,7 +176,8 @@ buffers_prefix_view<BufferSequence>::
|
||||
buffers_prefix_view(buffers_prefix_view const& other)
|
||||
: buffers_prefix_view(other,
|
||||
std::distance<iter_type>(
|
||||
other.bs_.begin(), other.end_))
|
||||
boost::asio::buffer_sequence_begin(other.bs_),
|
||||
other.end_))
|
||||
{
|
||||
}
|
||||
|
||||
@ -190,10 +188,13 @@ operator=(buffers_prefix_view&& other) ->
|
||||
buffers_prefix_view&
|
||||
{
|
||||
auto const dist = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.end_);
|
||||
boost::asio::buffer_sequence_begin(other.bs_),
|
||||
other.end_);
|
||||
bs_ = std::move(other.bs_);
|
||||
size_ = other.size_;
|
||||
end_ = std::next(bs_.begin(), dist);
|
||||
end_ = std::next(
|
||||
boost::asio::buffer_sequence_begin(bs_),
|
||||
dist);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -204,10 +205,13 @@ operator=(buffers_prefix_view const& other) ->
|
||||
buffers_prefix_view&
|
||||
{
|
||||
auto const dist = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.end_);
|
||||
boost::asio::buffer_sequence_begin(other.bs_),
|
||||
other.end_);
|
||||
bs_ = other.bs_;
|
||||
size_ = other.size_;
|
||||
end_ = std::next(bs_.begin(), dist);
|
||||
end_ = std::next(
|
||||
boost::asio::buffer_sequence_begin(bs_),
|
||||
dist);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -25,8 +25,8 @@ class buffers_suffix<Buffers>::const_iterator
|
||||
{
|
||||
friend class buffers_suffix<Buffers>;
|
||||
|
||||
using iter_type =
|
||||
typename Buffers::const_iterator;
|
||||
using iter_type = typename
|
||||
detail::buffer_sequence_iterator<Buffers>::type;
|
||||
|
||||
iter_type it_;
|
||||
buffers_suffix const* b_ = nullptr;
|
||||
@ -117,7 +117,7 @@ private:
|
||||
template<class Buffers>
|
||||
buffers_suffix<Buffers>::
|
||||
buffers_suffix()
|
||||
: begin_(bs_.begin())
|
||||
: begin_(boost::asio::buffer_sequence_begin(bs_))
|
||||
{
|
||||
}
|
||||
|
||||
@ -126,7 +126,8 @@ buffers_suffix<Buffers>::
|
||||
buffers_suffix(buffers_suffix&& other)
|
||||
: buffers_suffix(std::move(other),
|
||||
std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_))
|
||||
boost::asio::buffer_sequence_begin(
|
||||
other.bs_), other.begin_))
|
||||
{
|
||||
}
|
||||
|
||||
@ -135,7 +136,8 @@ buffers_suffix<Buffers>::
|
||||
buffers_suffix(buffers_suffix const& other)
|
||||
: buffers_suffix(other,
|
||||
std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_))
|
||||
boost::asio::buffer_sequence_begin(
|
||||
other.bs_), other.begin_))
|
||||
{
|
||||
}
|
||||
|
||||
@ -143,11 +145,11 @@ template<class Buffers>
|
||||
buffers_suffix<Buffers>::
|
||||
buffers_suffix(Buffers const& bs)
|
||||
: bs_(bs)
|
||||
, begin_(bs_.begin())
|
||||
, begin_(boost::asio::buffer_sequence_begin(bs_))
|
||||
{
|
||||
static_assert(
|
||||
is_const_buffer_sequence<Buffers>::value||
|
||||
is_mutable_buffer_sequence<Buffers>::value,
|
||||
boost::asio::is_const_buffer_sequence<Buffers>::value||
|
||||
boost::asio::is_mutable_buffer_sequence<Buffers>::value,
|
||||
"BufferSequence requirements not met");
|
||||
}
|
||||
|
||||
@ -156,7 +158,7 @@ template<class... Args>
|
||||
buffers_suffix<Buffers>::
|
||||
buffers_suffix(boost::in_place_init_t, Args&&... args)
|
||||
: bs_(std::forward<Args>(args)...)
|
||||
, begin_(bs_.begin())
|
||||
, begin_(boost::asio::buffer_sequence_begin(bs_))
|
||||
{
|
||||
static_assert(sizeof...(Args) > 0,
|
||||
"Missing constructor arguments");
|
||||
@ -172,9 +174,12 @@ operator=(buffers_suffix&& other) ->
|
||||
buffers_suffix&
|
||||
{
|
||||
auto const dist = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_);
|
||||
boost::asio::buffer_sequence_begin(other.bs_),
|
||||
other.begin_);
|
||||
bs_ = std::move(other.bs_);
|
||||
begin_ = std::next(bs_.begin(), dist);
|
||||
begin_ = std::next(
|
||||
boost::asio::buffer_sequence_begin(bs_),
|
||||
dist);
|
||||
skip_ = other.skip_;
|
||||
return *this;
|
||||
}
|
||||
@ -186,9 +191,11 @@ operator=(buffers_suffix const& other) ->
|
||||
buffers_suffix&
|
||||
{
|
||||
auto const dist = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_);
|
||||
boost::asio::buffer_sequence_begin(other.bs_),
|
||||
other.begin_);
|
||||
bs_ = other.bs_;
|
||||
begin_ = std::next(bs_.begin(), dist);
|
||||
begin_ = std::next(
|
||||
boost::asio::buffer_sequence_begin(bs_), dist);
|
||||
skip_ = other.skip_;
|
||||
return *this;
|
||||
}
|
||||
@ -210,7 +217,8 @@ buffers_suffix<Buffers>::
|
||||
end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*this, bs_.end()};
|
||||
return const_iterator{*this,
|
||||
boost::asio::buffer_sequence_end(bs_)};
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
@ -219,7 +227,9 @@ buffers_suffix<Buffers>::
|
||||
consume(std::size_t amount)
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
for(;amount > 0 && begin_ != bs_.end(); ++begin_)
|
||||
auto const end =
|
||||
boost::asio::buffer_sequence_end(bs_);
|
||||
for(;amount > 0 && begin_ != end; ++begin_)
|
||||
{
|
||||
auto const len =
|
||||
buffer_size(*begin_) - skip_;
|
||||
|
@ -10,9 +10,7 @@
|
||||
#ifndef BOOST_BEAST_IMPL_HANDLER_PTR_HPP
|
||||
#define BOOST_BEAST_IMPL_HANDLER_PTR_HPP
|
||||
|
||||
#include <boost/asio/handler_alloc_hook.hpp>
|
||||
#include <boost/asio/handler_continuation_hook.hpp>
|
||||
#include <boost/asio/handler_invoke_hook.hpp>
|
||||
#include <boost/asio/associated_allocator.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <memory>
|
||||
|
||||
@ -27,10 +25,11 @@ P(DeducedHandler&& h, Args&&... args)
|
||||
: n(1)
|
||||
, handler(std::forward<DeducedHandler>(h))
|
||||
{
|
||||
using boost::asio::asio_handler_allocate;
|
||||
t = reinterpret_cast<T*>(
|
||||
asio_handler_allocate(
|
||||
sizeof(T), std::addressof(handler)));
|
||||
typename std::allocator_traits<
|
||||
boost::asio::associated_allocator_t<Handler>>::
|
||||
template rebind_alloc<T> alloc{
|
||||
boost::asio::get_associated_allocator(handler)};
|
||||
t = std::allocator_traits<decltype(alloc)>::allocate(alloc, 1);
|
||||
try
|
||||
{
|
||||
t = new(t) T{handler,
|
||||
@ -38,9 +37,8 @@ P(DeducedHandler&& h, Args&&... args)
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
asio_handler_deallocate(
|
||||
t, sizeof(T), std::addressof(handler));
|
||||
std::allocator_traits<
|
||||
decltype(alloc)>::deallocate(alloc, t, 1);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
@ -56,9 +54,13 @@ handler_ptr<T, Handler>::
|
||||
if(p_->t)
|
||||
{
|
||||
p_->t->~T();
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
asio_handler_deallocate(
|
||||
p_->t, sizeof(T), std::addressof(p_->handler));
|
||||
typename std::allocator_traits<
|
||||
boost::asio::associated_allocator_t<Handler>>::
|
||||
template rebind_alloc<T> alloc{
|
||||
boost::asio::get_associated_allocator(
|
||||
p_->handler)};
|
||||
std::allocator_traits<
|
||||
decltype(alloc)>::deallocate(alloc, p_->t, 1);
|
||||
}
|
||||
delete p_;
|
||||
}
|
||||
@ -108,9 +110,13 @@ release_handler() ->
|
||||
BOOST_ASSERT(p_);
|
||||
BOOST_ASSERT(p_->t);
|
||||
p_->t->~T();
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
asio_handler_deallocate(
|
||||
p_->t, sizeof(T), std::addressof(p_->handler));
|
||||
typename std::allocator_traits<
|
||||
boost::asio::associated_allocator_t<Handler>>::
|
||||
template rebind_alloc<T> alloc{
|
||||
boost::asio::get_associated_allocator(
|
||||
p_->handler)};
|
||||
std::allocator_traits<
|
||||
decltype(alloc)>::deallocate(alloc, p_->t, 1);
|
||||
p_->t = nullptr;
|
||||
return std::move(p_->handler);
|
||||
}
|
||||
@ -124,9 +130,13 @@ invoke(Args&&... args)
|
||||
BOOST_ASSERT(p_);
|
||||
BOOST_ASSERT(p_->t);
|
||||
p_->t->~T();
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
asio_handler_deallocate(
|
||||
p_->t, sizeof(T), std::addressof(p_->handler));
|
||||
typename std::allocator_traits<
|
||||
boost::asio::associated_allocator_t<Handler>>::
|
||||
template rebind_alloc<T> alloc{
|
||||
boost::asio::get_associated_allocator(
|
||||
p_->handler)};
|
||||
std::allocator_traits<
|
||||
decltype(alloc)>::deallocate(alloc, p_->t, 1);
|
||||
p_->t = nullptr;
|
||||
p_->handler(std::forward<Args>(args)...);
|
||||
}
|
||||
|
@ -38,7 +38,8 @@ std::size_t
|
||||
read_size(DynamicBuffer& buffer,
|
||||
std::size_t max_size, std::false_type)
|
||||
{
|
||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||
static_assert(
|
||||
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||
"DynamicBuffer requirements not met");
|
||||
BOOST_ASSERT(max_size >= 1);
|
||||
auto const size = buffer.size();
|
||||
|
@ -49,7 +49,7 @@ detail::buffers_helper<ConstBufferSequence>
|
||||
#endif
|
||||
buffers(ConstBufferSequence const& b)
|
||||
{
|
||||
static_assert(is_const_buffer_sequence<
|
||||
static_assert(boost::asio::is_const_buffer_sequence<
|
||||
ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
return detail::buffers_helper<
|
||||
@ -90,7 +90,8 @@ detail::ostream_helper<
|
||||
#endif
|
||||
ostream(DynamicBuffer& buffer)
|
||||
{
|
||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||
static_assert(
|
||||
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||
"DynamicBuffer requirements not met");
|
||||
return detail::ostream_helper<
|
||||
DynamicBuffer, char, std::char_traits<char>,
|
||||
|
@ -19,153 +19,6 @@
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Buffer concepts
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Determine if `T` meets the requirements of @b ConstBufferSequence.
|
||||
|
||||
Metafunctions are used to perform compile time checking of template
|
||||
types. This type will be `std::true_type` if `T` meets the requirements,
|
||||
else the type will be `std::false_type`.
|
||||
|
||||
@par Example
|
||||
|
||||
Use with `static_assert`:
|
||||
|
||||
@code
|
||||
template<class ConstBufferSequence>
|
||||
void f(ConstBufferSequence const& buffers)
|
||||
{
|
||||
static_assert(is_const_buffer_sequence<ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
...
|
||||
@endcode
|
||||
|
||||
Use with `std::enable_if` (SFINAE):
|
||||
|
||||
@code
|
||||
template<class ConstBufferSequence>
|
||||
typename std::enable_if<is_const_buffer_sequence<ConstBufferSequence>::value>::type
|
||||
f(ConstBufferSequence const& buffers);
|
||||
@endcode
|
||||
*/
|
||||
template<class T>
|
||||
#if BOOST_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>
|
||||
#endif
|
||||
{
|
||||
};
|
||||
|
||||
/** Determine if `T` meets the requirements of @b MutableBufferSequence.
|
||||
|
||||
Metafunctions are used to perform compile time checking of template
|
||||
types. This type will be `std::true_type` if `T` meets the requirements,
|
||||
else the type will be `std::false_type`.
|
||||
|
||||
@par Example
|
||||
|
||||
Use with `static_assert`:
|
||||
|
||||
@code
|
||||
template<class MutableBufferSequence>
|
||||
void f(MutableBufferSequence const& buffers)
|
||||
{
|
||||
static_assert(is_const_buffer_sequence<MutableBufferSequence>::value,
|
||||
"MutableBufferSequence requirements not met");
|
||||
...
|
||||
@endcode
|
||||
|
||||
Use with `std::enable_if` (SFINAE):
|
||||
|
||||
@code
|
||||
template<class MutableBufferSequence>
|
||||
typename std::enable_if<is_mutable_buffer_sequence<MutableBufferSequence>::value>::type
|
||||
f(MutableBufferSequence const& buffers);
|
||||
@endcode
|
||||
*/
|
||||
template<class T>
|
||||
#if BOOST_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>
|
||||
#endif
|
||||
{
|
||||
};
|
||||
|
||||
/** Determine if `T` meets the requirements of @b DynamicBuffer.
|
||||
|
||||
Metafunctions are used to perform compile time checking of template
|
||||
types. This type will be `std::true_type` if `T` meets the requirements,
|
||||
else the type will be `std::false_type`.
|
||||
|
||||
@par Example
|
||||
|
||||
Use with `static_assert`:
|
||||
|
||||
@code
|
||||
template<class DynamicBuffer>
|
||||
void f(DynamicBuffer& buffer)
|
||||
{
|
||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||
"DynamicBuffer requirements not met");
|
||||
...
|
||||
@endcode
|
||||
|
||||
Use with `std::enable_if` (SFINAE):
|
||||
|
||||
@code
|
||||
template<class DynamicBuffer>
|
||||
typename std::enable_if<is_dynamic_buffer<DynamicBuffer>::value>::type
|
||||
f(DynamicBuffer const& buffer);
|
||||
@endcode
|
||||
*/
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
template<class T>
|
||||
struct is_dynamic_buffer : std::integral_constant<bool, ...> {};
|
||||
#else
|
||||
template<class T, class = void>
|
||||
struct is_dynamic_buffer : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct is_dynamic_buffer<T, detail::void_t<decltype(
|
||||
std::declval<std::size_t&>() =
|
||||
std::declval<T const&>().size(),
|
||||
std::declval<std::size_t&>() =
|
||||
std::declval<T const&>().max_size(),
|
||||
std::declval<std::size_t&>() =
|
||||
std::declval<T const&>().capacity(),
|
||||
std::declval<T&>().commit(std::declval<std::size_t>()),
|
||||
std::declval<T&>().consume(std::declval<std::size_t>()),
|
||||
(void)0)> > : std::integral_constant<bool,
|
||||
is_const_buffer_sequence<
|
||||
typename T::const_buffers_type>::value &&
|
||||
is_mutable_buffer_sequence<
|
||||
typename T::mutable_buffers_type>::value &&
|
||||
std::is_same<typename T::const_buffers_type,
|
||||
decltype(std::declval<T const&>().data())>::value &&
|
||||
std::is_same<typename T::mutable_buffers_type,
|
||||
decltype(std::declval<T&>().prepare(
|
||||
std::declval<std::size_t>()))>::value
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
// Special case for Boost.Asio which doesn't adhere to
|
||||
// net-ts but still provides a read_size_helper so things work
|
||||
template<class Allocator>
|
||||
struct is_dynamic_buffer<
|
||||
boost::asio::basic_streambuf<Allocator>> : std::true_type
|
||||
{
|
||||
};
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Handler concepts
|
||||
@ -209,7 +62,7 @@ using is_completion_handler = std::integral_constant<bool,
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Determine if `T` has the `get_io_service` member.
|
||||
/** Determine if `T` has the `get_executor` member function.
|
||||
|
||||
Metafunctions are used to perform compile time checking of template
|
||||
types. This type will be `std::true_type` if `T` has the member
|
||||
@ -223,19 +76,24 @@ using is_completion_handler = std::integral_constant<bool,
|
||||
template<class T>
|
||||
void maybe_hello(T& t, std::true_type)
|
||||
{
|
||||
t.get_io_service().post([]{ std::cout << "Hello, world!" << std::endl; });
|
||||
boost::asio::post(
|
||||
t.get_executor(),
|
||||
[]
|
||||
{
|
||||
std::cout << "Hello, world!" << std::endl;
|
||||
});
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void maybe_hello(T&, std::false_type)
|
||||
{
|
||||
// T does not have get_io_service
|
||||
// T does not have get_executor
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void maybe_hello(T& t)
|
||||
{
|
||||
maybe_hello(t, has_get_io_service<T>{});
|
||||
maybe_hello(t, has_get_executor<T>{});
|
||||
}
|
||||
@endcode
|
||||
|
||||
@ -244,24 +102,23 @@ using is_completion_handler = std::integral_constant<bool,
|
||||
@code
|
||||
struct stream
|
||||
{
|
||||
boost::asio::io_service& get_io_service();
|
||||
using executor_type = boost::asio::io_context::executor_type;
|
||||
executor_type get_executor() noexcept;
|
||||
};
|
||||
|
||||
static_assert(has_get_io_service<stream>::value,
|
||||
"Missing get_io_service member");
|
||||
static_assert(has_get_executor<stream>::value, "Missing get_executor member");
|
||||
@endcode
|
||||
*/
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
template<class T>
|
||||
struct has_get_io_service : std::integral_constant<bool, ...>{};
|
||||
struct has_get_executor : std::integral_constant<bool, ...>{};
|
||||
#else
|
||||
template<class T, class = void>
|
||||
struct has_get_io_service : std::false_type {};
|
||||
struct has_get_executor : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct has_get_io_service<T, beast::detail::void_t<decltype(
|
||||
detail::accept_rv<boost::asio::io_service&>(
|
||||
std::declval<T&>().get_io_service()),
|
||||
struct has_get_executor<T, beast::detail::void_t<decltype(
|
||||
std::declval<T&>().get_executor(),
|
||||
(void)0)>> : std::true_type {};
|
||||
#endif
|
||||
|
||||
@ -350,7 +207,7 @@ struct is_async_read_stream<T, detail::void_t<decltype(
|
||||
std::declval<detail::MutableBufferSequence>(),
|
||||
std::declval<detail::ReadHandler>()),
|
||||
(void)0)>> : std::integral_constant<bool,
|
||||
has_get_io_service<T>::value
|
||||
has_get_executor<T>::value
|
||||
> {};
|
||||
#endif
|
||||
|
||||
@ -394,7 +251,7 @@ struct is_async_write_stream<T, detail::void_t<decltype(
|
||||
std::declval<detail::ConstBufferSequence>(),
|
||||
std::declval<detail::WriteHandler>()),
|
||||
(void)0)>> : std::integral_constant<bool,
|
||||
has_get_io_service<T>::value
|
||||
has_get_executor<T>::value
|
||||
> {};
|
||||
#endif
|
||||
|
||||
@ -439,12 +296,10 @@ struct is_sync_read_stream<T, detail::void_t<decltype(
|
||||
std::declval<std::size_t&>() = std::declval<T>().read_some(
|
||||
std::declval<detail::MutableBufferSequence>(),
|
||||
std::declval<boost::system::error_code&>()),
|
||||
(void)0)>> : std::integral_constant<bool,
|
||||
has_get_io_service<T>::value
|
||||
> {};
|
||||
(void)0)>> : std::true_type {};
|
||||
#endif
|
||||
|
||||
/** Determine if `T` meets the requirements of @b SyncWriterStream.
|
||||
/** Determine if `T` meets the requirements of @b SyncWriteStream.
|
||||
|
||||
Metafunctions are used to perform compile time checking of template
|
||||
types. This type will be `std::true_type` if `T` meets the requirements,
|
||||
@ -485,9 +340,7 @@ struct is_sync_write_stream<T, detail::void_t<decltype(
|
||||
std::declval<std::size_t&>() = std::declval<T&>().write_some(
|
||||
std::declval<detail::ConstBufferSequence>(),
|
||||
std::declval<boost::system::error_code&>()),
|
||||
(void)0)>> : std::integral_constant<bool,
|
||||
has_get_io_service<T>::value
|
||||
> {};
|
||||
(void)0)>> : std::true_type {};
|
||||
#endif
|
||||
|
||||
/** Determine if `T` meets the requirements of @b AsyncStream.
|
||||
|
@ -32,7 +32,8 @@ namespace http {
|
||||
template<class DynamicBuffer>
|
||||
struct basic_dynamic_body
|
||||
{
|
||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||
static_assert(
|
||||
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||
"DynamicBuffer requirements not met");
|
||||
|
||||
/** The type of container used for the body
|
||||
|
@ -143,7 +143,13 @@ public:
|
||||
|
||||
/** Set the open file
|
||||
|
||||
This function is used to set the open
|
||||
This function is used to set the open file. Any previously
|
||||
set file will be closed.
|
||||
|
||||
@param file The file to set. The file must be open or else
|
||||
an error occurs
|
||||
|
||||
@param ec Set to the error, if any occurred
|
||||
*/
|
||||
void
|
||||
reset(File&& file, error_code& ec);
|
||||
@ -229,7 +235,7 @@ public:
|
||||
// The type of buffer sequence returned by `get`.
|
||||
//
|
||||
using const_buffers_type =
|
||||
boost::asio::const_buffers_1;
|
||||
boost::asio::const_buffer;
|
||||
|
||||
// Constructor.
|
||||
//
|
||||
@ -485,13 +491,13 @@ put(ConstBufferSequence const& buffers, error_code& ec)
|
||||
|
||||
// Loop over all the buffers in the sequence,
|
||||
// and write each one to the file.
|
||||
for(boost::asio::const_buffer buffer : buffers)
|
||||
for(auto it = boost::asio::buffer_sequence_begin(buffers);
|
||||
it != boost::asio::buffer_sequence_end(buffers); ++it)
|
||||
{
|
||||
// Write this buffer to the file
|
||||
boost::asio::const_buffer buffer = *it;
|
||||
nwritten += body_.file_.write(
|
||||
boost::asio::buffer_cast<void const*>(buffer),
|
||||
boost::asio::buffer_size(buffer),
|
||||
ec);
|
||||
buffer.data(), buffer.size(), ec);
|
||||
if(ec)
|
||||
return nwritten;
|
||||
}
|
||||
|
@ -515,7 +515,7 @@ public:
|
||||
|
||||
#if ! BOOST_BEAST_DOXYGEN
|
||||
std::size_t
|
||||
put(boost::asio::const_buffers_1 const& buffer,
|
||||
put(boost::asio::const_buffer const& buffer,
|
||||
error_code& ec);
|
||||
#endif
|
||||
|
||||
|
@ -105,7 +105,7 @@ struct buffer_body
|
||||
|
||||
public:
|
||||
using const_buffers_type =
|
||||
boost::asio::const_buffers_1;
|
||||
boost::asio::const_buffer;
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
|
@ -106,7 +106,7 @@ class chunk_header
|
||||
{
|
||||
using view_type = buffers_cat_view<
|
||||
detail::chunk_size, // chunk-size
|
||||
boost::asio::const_buffers_1, // chunk-extensions
|
||||
boost::asio::const_buffer, // chunk-extensions
|
||||
chunk_crlf>; // CRLF
|
||||
|
||||
std::shared_ptr<
|
||||
@ -285,7 +285,7 @@ class chunk_body
|
||||
{
|
||||
using view_type = buffers_cat_view<
|
||||
detail::chunk_size, // chunk-size
|
||||
boost::asio::const_buffers_1, // chunk-extensions
|
||||
boost::asio::const_buffer, // chunk-extensions
|
||||
chunk_crlf, // CRLF
|
||||
ConstBufferSequence, // chunk-body
|
||||
chunk_crlf>; // CRLF
|
||||
@ -459,7 +459,7 @@ class chunk_last
|
||||
{
|
||||
static_assert(
|
||||
is_fields<Trailer>::value ||
|
||||
is_const_buffer_sequence<Trailer>::value,
|
||||
boost::asio::is_const_buffer_sequence<Trailer>::value,
|
||||
"Trailer requirements not met");
|
||||
|
||||
using buffers_type = typename
|
||||
|
@ -25,7 +25,7 @@ namespace detail {
|
||||
struct chunk_extensions
|
||||
{
|
||||
virtual ~chunk_extensions() = default;
|
||||
virtual boost::asio::const_buffers_1 str() = 0;
|
||||
virtual boost::asio::const_buffer str() = 0;
|
||||
};
|
||||
|
||||
template<class ChunkExtensions>
|
||||
@ -43,7 +43,7 @@ struct chunk_extensions_impl : chunk_extensions
|
||||
{
|
||||
}
|
||||
|
||||
boost::asio::const_buffers_1
|
||||
boost::asio::const_buffer
|
||||
str() override
|
||||
{
|
||||
auto const s = ext_.str();
|
||||
@ -151,7 +151,7 @@ prepare(std::size_t n)
|
||||
|
||||
/// Returns a buffer sequence holding a CRLF for chunk encoding
|
||||
inline
|
||||
boost::asio::const_buffers_1
|
||||
boost::asio::const_buffer
|
||||
chunk_crlf()
|
||||
{
|
||||
return {"\r\n", 2};
|
||||
@ -159,7 +159,7 @@ chunk_crlf()
|
||||
|
||||
/// Returns a buffer sequence holding a final chunk header
|
||||
inline
|
||||
boost::asio::const_buffers_1
|
||||
boost::asio::const_buffer
|
||||
chunk_last()
|
||||
{
|
||||
return {"0\r\n", 3};
|
||||
|
@ -103,14 +103,13 @@ basic_parser<isRequest, Derived>::
|
||||
put(ConstBufferSequence const& buffers,
|
||||
error_code& ec)
|
||||
{
|
||||
static_assert(is_const_buffer_sequence<
|
||||
static_assert(boost::asio::is_const_buffer_sequence<
|
||||
ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_copy;
|
||||
using boost::asio::buffer_size;
|
||||
auto const p = buffers.begin();
|
||||
auto const last = buffers.end();
|
||||
auto const p = boost::asio::buffer_sequence_begin(buffers);
|
||||
auto const last = boost::asio::buffer_sequence_end(buffers);
|
||||
if(p == last)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
@ -119,10 +118,7 @@ put(ConstBufferSequence const& buffers,
|
||||
if(std::next(p) == last)
|
||||
{
|
||||
// single buffer
|
||||
auto const b = *p;
|
||||
return put(boost::asio::const_buffers_1{
|
||||
buffer_cast<char const*>(b),
|
||||
buffer_size(b)}, ec);
|
||||
return put(boost::asio::const_buffer(*p), ec);
|
||||
}
|
||||
auto const size = buffer_size(buffers);
|
||||
if(size <= max_stack_buffer)
|
||||
@ -136,21 +132,21 @@ put(ConstBufferSequence const& buffers,
|
||||
// flatten
|
||||
buffer_copy(boost::asio::buffer(
|
||||
buf_.get(), buf_len_), buffers);
|
||||
return put(boost::asio::const_buffers_1{
|
||||
return put(boost::asio::const_buffer{
|
||||
buf_.get(), buf_len_}, ec);
|
||||
}
|
||||
|
||||
template<bool isRequest, class Derived>
|
||||
std::size_t
|
||||
basic_parser<isRequest, Derived>::
|
||||
put(boost::asio::const_buffers_1 const& buffer,
|
||||
put(boost::asio::const_buffer const& buffer,
|
||||
error_code& ec)
|
||||
{
|
||||
BOOST_ASSERT(state_ != state::complete);
|
||||
using boost::asio::buffer_size;
|
||||
auto p = boost::asio::buffer_cast<
|
||||
char const*>(*buffer.begin());
|
||||
auto n = buffer_size(*buffer.begin());
|
||||
auto p = reinterpret_cast<
|
||||
char const*>(buffer.data());
|
||||
auto n = buffer.size();
|
||||
auto const p0 = p;
|
||||
auto const p1 = p0 + n;
|
||||
ec.assign(0, ec.category());
|
||||
@ -324,7 +320,7 @@ put_from_stack(std::size_t size,
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_copy;
|
||||
buffer_copy(buffer(buf, sizeof(buf)), buffers);
|
||||
return put(boost::asio::const_buffers_1{
|
||||
return put(boost::asio::const_buffer{
|
||||
buf, size}, ec);
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ chunk_header::
|
||||
chunk_header(std::size_t size)
|
||||
: view_(
|
||||
size,
|
||||
boost::asio::const_buffers_1{nullptr, 0},
|
||||
boost::asio::const_buffer{nullptr, 0},
|
||||
chunk_crlf{})
|
||||
{
|
||||
BOOST_ASSERT(size > 0);
|
||||
@ -37,7 +37,7 @@ chunk_header(
|
||||
string_view extensions)
|
||||
: view_(
|
||||
size,
|
||||
boost::asio::const_buffers_1{
|
||||
boost::asio::const_buffer{
|
||||
extensions.data(), extensions.size()},
|
||||
chunk_crlf{})
|
||||
{
|
||||
@ -90,7 +90,7 @@ chunk_body<ConstBufferSequence>::
|
||||
chunk_body(ConstBufferSequence const& buffers)
|
||||
: view_(
|
||||
boost::asio::buffer_size(buffers),
|
||||
boost::asio::const_buffers_1{nullptr, 0},
|
||||
boost::asio::const_buffer{nullptr, 0},
|
||||
chunk_crlf{},
|
||||
buffers,
|
||||
chunk_crlf{})
|
||||
@ -104,7 +104,7 @@ chunk_body(
|
||||
string_view extensions)
|
||||
: view_(
|
||||
boost::asio::buffer_size(buffers),
|
||||
boost::asio::const_buffers_1{
|
||||
boost::asio::const_buffer{
|
||||
extensions.data(), extensions.size()},
|
||||
chunk_crlf{},
|
||||
buffers,
|
||||
|
@ -143,9 +143,9 @@ public:
|
||||
};
|
||||
|
||||
using view_type = buffers_cat_view<
|
||||
boost::asio::const_buffers_1,
|
||||
boost::asio::const_buffers_1,
|
||||
boost::asio::const_buffers_1,
|
||||
boost::asio::const_buffer,
|
||||
boost::asio::const_buffer,
|
||||
boost::asio::const_buffer,
|
||||
field_range,
|
||||
chunk_crlf>;
|
||||
|
||||
@ -178,9 +178,9 @@ reader(basic_fields const& f)
|
||||
: f_(f)
|
||||
{
|
||||
view_.emplace(
|
||||
boost::asio::const_buffers_1{nullptr, 0},
|
||||
boost::asio::const_buffers_1{nullptr, 0},
|
||||
boost::asio::const_buffers_1{nullptr, 0},
|
||||
boost::asio::const_buffer{nullptr, 0},
|
||||
boost::asio::const_buffer{nullptr, 0},
|
||||
boost::asio::const_buffer{nullptr, 0},
|
||||
field_range(f_.list_.begin(), f_.list_.end()),
|
||||
chunk_crlf());
|
||||
}
|
||||
@ -218,11 +218,11 @@ reader(basic_fields const& f,
|
||||
buf_[10]= '\n';
|
||||
|
||||
view_.emplace(
|
||||
boost::asio::const_buffers_1{sv.data(), sv.size()},
|
||||
boost::asio::const_buffers_1{
|
||||
boost::asio::const_buffer{sv.data(), sv.size()},
|
||||
boost::asio::const_buffer{
|
||||
f_.target_or_reason_.data(),
|
||||
f_.target_or_reason_.size()},
|
||||
boost::asio::const_buffers_1{buf_, 11},
|
||||
boost::asio::const_buffer{buf_, 11},
|
||||
field_range(f_.list_.begin(), f_.list_.end()),
|
||||
chunk_crlf());
|
||||
}
|
||||
@ -260,9 +260,9 @@ reader(basic_fields const& f,
|
||||
sv = obsolete_reason(static_cast<status>(code));
|
||||
|
||||
view_.emplace(
|
||||
boost::asio::const_buffers_1{buf_, 13},
|
||||
boost::asio::const_buffers_1{sv.data(), sv.size()},
|
||||
boost::asio::const_buffers_1{"\r\n", 2},
|
||||
boost::asio::const_buffer{buf_, 13},
|
||||
boost::asio::const_buffer{sv.data(), sv.size()},
|
||||
boost::asio::const_buffer{"\r\n", 2},
|
||||
field_range(f_.list_.begin(), f_.list_.end()),
|
||||
chunk_crlf{});
|
||||
}
|
||||
|
@ -12,15 +12,15 @@
|
||||
|
||||
#if BOOST_BEAST_USE_WIN32_FILE
|
||||
|
||||
#include <boost/beast/core/async_result.hpp>
|
||||
#include <boost/beast/core/bind_handler.hpp>
|
||||
#include <boost/beast/core/type_traits.hpp>
|
||||
#include <boost/beast/core/detail/clamp.hpp>
|
||||
#include <boost/beast/http/serializer.hpp>
|
||||
#include <boost/asio/associated_allocator.hpp>
|
||||
#include <boost/asio/associated_executor.hpp>
|
||||
#include <boost/asio/async_result.hpp>
|
||||
#include <boost/asio/basic_stream_socket.hpp>
|
||||
#include <boost/asio/handler_alloc_hook.hpp>
|
||||
#include <boost/asio/handler_continuation_hook.hpp>
|
||||
#include <boost/asio/handler_invoke_hook.hpp>
|
||||
#include <boost/asio/windows/overlapped_ptr.hpp>
|
||||
#include <boost/make_unique.hpp>
|
||||
#include <boost/smart_ptr/make_shared_array.hpp>
|
||||
@ -120,7 +120,7 @@ struct basic_file_body<file_win32>
|
||||
|
||||
public:
|
||||
using const_buffers_type =
|
||||
boost::asio::const_buffers_1;
|
||||
boost::asio::const_buffer;
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
reader(message<isRequest,
|
||||
@ -189,12 +189,10 @@ struct basic_file_body<file_win32>
|
||||
error_code& ec)
|
||||
{
|
||||
std::size_t nwritten = 0;
|
||||
for(boost::asio::const_buffer buffer : buffers)
|
||||
for(auto buffer : beast::detail::buffers_range(buffers))
|
||||
{
|
||||
nwritten += body_.file_.write(
|
||||
boost::asio::buffer_cast<void const*>(buffer),
|
||||
boost::asio::buffer_size(buffer),
|
||||
ec);
|
||||
buffer.data(), buffer.size(), ec);
|
||||
if(ec)
|
||||
return nwritten;
|
||||
}
|
||||
@ -360,6 +358,24 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
using allocator_type =
|
||||
boost::asio::associated_allocator_t<Handler>;
|
||||
|
||||
allocator_type
|
||||
get_allocator() const noexcept
|
||||
{
|
||||
return boost::asio::get_associated_allocator(h_);
|
||||
}
|
||||
|
||||
using executor_type = boost::asio::associated_executor_t<
|
||||
Handler, decltype(sock_.get_executor())>;
|
||||
|
||||
executor_type get_executor() const noexcept
|
||||
{
|
||||
return boost::asio::get_associated_executor(
|
||||
h_, sock_.get_executor());
|
||||
}
|
||||
|
||||
void
|
||||
operator()();
|
||||
|
||||
@ -368,24 +384,6 @@ public:
|
||||
error_code ec,
|
||||
std::size_t bytes_transferred = 0);
|
||||
|
||||
friend
|
||||
void* asio_handler_allocate(
|
||||
std::size_t size, write_some_win32_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_allocate;
|
||||
return asio_handler_allocate(
|
||||
size, std::addressof(op->h_));
|
||||
}
|
||||
|
||||
friend
|
||||
void asio_handler_deallocate(
|
||||
void* p, std::size_t size, write_some_win32_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
asio_handler_deallocate(
|
||||
p, size, std::addressof(op->h_));
|
||||
}
|
||||
|
||||
friend
|
||||
bool asio_handler_is_continuation(write_some_win32_op* op)
|
||||
{
|
||||
@ -393,15 +391,6 @@ public:
|
||||
return asio_handler_is_continuation(
|
||||
std::addressof(op->h_));
|
||||
}
|
||||
|
||||
template<class Function>
|
||||
friend
|
||||
void asio_handler_invoke(Function&& f, write_some_win32_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_invoke;
|
||||
asio_handler_invoke(
|
||||
f, std::addressof(op->h_));
|
||||
}
|
||||
};
|
||||
|
||||
template<
|
||||
@ -431,7 +420,7 @@ operator()()
|
||||
r.body_.last_ - r.pos_, sr_.limit())),
|
||||
2147483646);
|
||||
boost::asio::windows::overlapped_ptr overlapped{
|
||||
sock_.get_io_service(), *this};
|
||||
sock_.get_executor().context(), *this};
|
||||
auto& ov = *overlapped.get();
|
||||
ov.Offset = lowPart(r.pos_);
|
||||
ov.OffsetHigh = highPart(r.pos_);
|
||||
@ -567,21 +556,20 @@ template<
|
||||
class Protocol,
|
||||
bool isRequest, class Fields,
|
||||
class WriteHandler>
|
||||
async_return_type<
|
||||
WriteHandler,
|
||||
void(error_code, std::size_t)>
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||
WriteHandler, void(error_code, std::size_t))
|
||||
async_write_some(
|
||||
boost::asio::basic_stream_socket<Protocol>& sock,
|
||||
serializer<isRequest,
|
||||
basic_file_body<file_win32>, Fields>& sr,
|
||||
WriteHandler&& handler)
|
||||
{
|
||||
async_completion<WriteHandler,
|
||||
boost::asio::async_completion<WriteHandler,
|
||||
void(error_code)> init{handler};
|
||||
detail::write_some_win32_op<
|
||||
Protocol,
|
||||
handler_type<WriteHandler,
|
||||
void(error_code, std::size_t)>,
|
||||
BOOST_ASIO_HANDLER_TYPE(WriteHandler,
|
||||
void(error_code, std::size_t)),
|
||||
isRequest, Fields>{
|
||||
init.completion_handler, sock, sr}();
|
||||
return init.result.get();
|
||||
|
@ -18,9 +18,10 @@
|
||||
#include <boost/beast/core/handler_ptr.hpp>
|
||||
#include <boost/beast/core/read_size.hpp>
|
||||
#include <boost/beast/core/type_traits.hpp>
|
||||
#include <boost/asio/handler_alloc_hook.hpp>
|
||||
#include <boost/asio/associated_allocator.hpp>
|
||||
#include <boost/asio/associated_executor.hpp>
|
||||
#include <boost/asio/handler_continuation_hook.hpp>
|
||||
#include <boost/asio/handler_invoke_hook.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
@ -61,29 +62,29 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
using allocator_type =
|
||||
boost::asio::associated_allocator_t<Handler>;
|
||||
|
||||
allocator_type
|
||||
get_allocator() const noexcept
|
||||
{
|
||||
return boost::asio::get_associated_allocator(h_);
|
||||
}
|
||||
|
||||
using executor_type = boost::asio::associated_executor_t<
|
||||
Handler, decltype(s_.get_executor())>;
|
||||
|
||||
executor_type get_executor() const noexcept
|
||||
{
|
||||
return boost::asio::get_associated_executor(
|
||||
h_, s_.get_executor());
|
||||
}
|
||||
|
||||
void
|
||||
operator()(
|
||||
error_code ec = {},
|
||||
std::size_t bytes_transferred = 0);
|
||||
|
||||
friend
|
||||
void* asio_handler_allocate(
|
||||
std::size_t size, read_some_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_allocate;
|
||||
return asio_handler_allocate(
|
||||
size, std::addressof(op->h_));
|
||||
}
|
||||
|
||||
friend
|
||||
void asio_handler_deallocate(
|
||||
void* p, std::size_t size, read_some_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
asio_handler_deallocate(
|
||||
p, size, std::addressof(op->h_));
|
||||
}
|
||||
|
||||
friend
|
||||
bool asio_handler_is_continuation(read_some_op* op)
|
||||
{
|
||||
@ -92,15 +93,6 @@ public:
|
||||
asio_handler_is_continuation(
|
||||
std::addressof(op->h_));
|
||||
}
|
||||
|
||||
template<class Function>
|
||||
friend
|
||||
void asio_handler_invoke(Function&& f, read_some_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_invoke;
|
||||
asio_handler_invoke(
|
||||
f, std::addressof(op->h_));
|
||||
}
|
||||
};
|
||||
|
||||
template<class Stream, class DynamicBuffer,
|
||||
@ -170,7 +162,8 @@ operator()(
|
||||
if(state_ >= 2)
|
||||
goto upcall;
|
||||
state_ = 3;
|
||||
return s_.get_io_service().post(
|
||||
return boost::asio::post(
|
||||
s_.get_executor(),
|
||||
bind_handler(std::move(*this), ec, 0));
|
||||
|
||||
case 3:
|
||||
@ -231,29 +224,29 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
using allocator_type =
|
||||
boost::asio::associated_allocator_t<Handler>;
|
||||
|
||||
allocator_type
|
||||
get_allocator() const noexcept
|
||||
{
|
||||
return boost::asio::get_associated_allocator(h_);
|
||||
}
|
||||
|
||||
using executor_type = boost::asio::associated_executor_t<
|
||||
Handler, decltype(s_.get_executor())>;
|
||||
|
||||
executor_type get_executor() const noexcept
|
||||
{
|
||||
return boost::asio::get_associated_executor(
|
||||
h_, s_.get_executor());
|
||||
}
|
||||
|
||||
void
|
||||
operator()(
|
||||
error_code ec = {},
|
||||
std::size_t bytes_transferred = 0);
|
||||
|
||||
friend
|
||||
void* asio_handler_allocate(
|
||||
std::size_t size, read_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_allocate;
|
||||
return asio_handler_allocate(
|
||||
size, std::addressof(op->h_));
|
||||
}
|
||||
|
||||
friend
|
||||
void asio_handler_deallocate(
|
||||
void* p, std::size_t size, read_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
asio_handler_deallocate(
|
||||
p, size, std::addressof(op->h_));
|
||||
}
|
||||
|
||||
friend
|
||||
bool asio_handler_is_continuation(read_op* op)
|
||||
{
|
||||
@ -262,15 +255,6 @@ public:
|
||||
asio_handler_is_continuation(
|
||||
std::addressof(op->h_));
|
||||
}
|
||||
|
||||
template<class Function>
|
||||
friend
|
||||
void asio_handler_invoke(Function&& f, read_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_invoke;
|
||||
asio_handler_invoke(
|
||||
f, std::addressof(op->h_));
|
||||
}
|
||||
};
|
||||
|
||||
template<class Stream, class DynamicBuffer,
|
||||
@ -289,7 +273,8 @@ operator()(
|
||||
if(Condition{}(p_))
|
||||
{
|
||||
state_ = 1;
|
||||
return s_.get_io_service().post(
|
||||
return boost::asio::post(
|
||||
s_.get_executor(),
|
||||
bind_handler(std::move(*this), ec));
|
||||
}
|
||||
state_ = 2;
|
||||
@ -361,29 +346,29 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
using allocator_type =
|
||||
boost::asio::associated_allocator_t<Handler>;
|
||||
|
||||
allocator_type
|
||||
get_allocator() const noexcept
|
||||
{
|
||||
return boost::asio::get_associated_allocator(d_.handler());
|
||||
}
|
||||
|
||||
using executor_type = boost::asio::associated_executor_t<
|
||||
Handler, decltype(d_->s.get_executor())>;
|
||||
|
||||
executor_type get_executor() const noexcept
|
||||
{
|
||||
return boost::asio::get_associated_executor(
|
||||
d_.handler(), d_->s.get_executor());
|
||||
}
|
||||
|
||||
void
|
||||
operator()(
|
||||
error_code ec = {},
|
||||
std::size_t bytes_transferred = 0);
|
||||
|
||||
friend
|
||||
void* asio_handler_allocate(
|
||||
std::size_t size, read_msg_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_allocate;
|
||||
return asio_handler_allocate(
|
||||
size, std::addressof(op->d_.handler()));
|
||||
}
|
||||
|
||||
friend
|
||||
void asio_handler_deallocate(
|
||||
void* p, std::size_t size, read_msg_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
asio_handler_deallocate(
|
||||
p, size, std::addressof(op->d_.handler()));
|
||||
}
|
||||
|
||||
friend
|
||||
bool asio_handler_is_continuation(read_msg_op* op)
|
||||
{
|
||||
@ -392,15 +377,6 @@ public:
|
||||
asio_handler_is_continuation(
|
||||
std::addressof(op->d_.handler()));
|
||||
}
|
||||
|
||||
template<class Function>
|
||||
friend
|
||||
void asio_handler_invoke(Function&& f, read_msg_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_invoke;
|
||||
asio_handler_invoke(
|
||||
f, std::addressof(op->d_.handler()));
|
||||
}
|
||||
};
|
||||
|
||||
template<class Stream, class DynamicBuffer,
|
||||
@ -458,7 +434,8 @@ read_some(
|
||||
{
|
||||
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
||||
"SyncReadStream requirements not met");
|
||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||
static_assert(
|
||||
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||
"DynamicBuffer requirements not met");
|
||||
BOOST_ASSERT(! parser.is_done());
|
||||
error_code ec;
|
||||
@ -482,7 +459,8 @@ read_some(
|
||||
{
|
||||
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
||||
"SyncReadStream requirements not met");
|
||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||
static_assert(
|
||||
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||
"DynamicBuffer requirements not met");
|
||||
BOOST_ASSERT(! parser.is_done());
|
||||
std::size_t bytes_transferred = 0;
|
||||
@ -541,8 +519,8 @@ template<
|
||||
class DynamicBuffer,
|
||||
bool isRequest, class Derived,
|
||||
class ReadHandler>
|
||||
async_return_type<
|
||||
ReadHandler, void(error_code, std::size_t)>
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||
ReadHandler, void(error_code, std::size_t))
|
||||
async_read_some(
|
||||
AsyncReadStream& stream,
|
||||
DynamicBuffer& buffer,
|
||||
@ -551,13 +529,14 @@ async_read_some(
|
||||
{
|
||||
static_assert(is_async_read_stream<AsyncReadStream>::value,
|
||||
"AsyncReadStream requirements not met");
|
||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||
static_assert(
|
||||
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||
"DynamicBuffer requirements not met");
|
||||
BOOST_ASSERT(! parser.is_done());
|
||||
async_completion<ReadHandler, void(error_code)> init{handler};
|
||||
boost::asio::async_completion<ReadHandler, void(error_code)> init{handler};
|
||||
detail::read_some_op<AsyncReadStream,
|
||||
DynamicBuffer, isRequest, Derived, handler_type<
|
||||
ReadHandler, void(error_code, std::size_t)>>{
|
||||
DynamicBuffer, isRequest, Derived, BOOST_ASIO_HANDLER_TYPE(
|
||||
ReadHandler, void(error_code, std::size_t))>{
|
||||
init.completion_handler, stream, buffer, parser}();
|
||||
return init.result.get();
|
||||
}
|
||||
@ -576,7 +555,8 @@ read_header(
|
||||
{
|
||||
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
||||
"SyncReadStream requirements not met");
|
||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||
static_assert(
|
||||
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||
"DynamicBuffer requirements not met");
|
||||
error_code ec;
|
||||
auto const bytes_transferred =
|
||||
@ -599,7 +579,8 @@ read_header(
|
||||
{
|
||||
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
||||
"SyncReadStream requirements not met");
|
||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||
static_assert(
|
||||
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||
"DynamicBuffer requirements not met");
|
||||
parser.eager(false);
|
||||
if(parser.is_header_done())
|
||||
@ -624,9 +605,8 @@ template<
|
||||
class DynamicBuffer,
|
||||
bool isRequest, class Derived,
|
||||
class ReadHandler>
|
||||
async_return_type<
|
||||
ReadHandler,
|
||||
void(error_code, std::size_t)>
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||
ReadHandler, void(error_code, std::size_t))
|
||||
async_read_header(
|
||||
AsyncReadStream& stream,
|
||||
DynamicBuffer& buffer,
|
||||
@ -635,14 +615,15 @@ async_read_header(
|
||||
{
|
||||
static_assert(is_async_read_stream<AsyncReadStream>::value,
|
||||
"AsyncReadStream requirements not met");
|
||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||
static_assert(
|
||||
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||
"DynamicBuffer requirements not met");
|
||||
parser.eager(false);
|
||||
async_completion<ReadHandler,
|
||||
boost::asio::async_completion<ReadHandler,
|
||||
void(error_code, std::size_t)> init{handler};
|
||||
detail::read_op<AsyncReadStream, DynamicBuffer,
|
||||
isRequest, Derived, detail::parser_is_header_done,
|
||||
handler_type<ReadHandler, void(error_code, std::size_t)>>{
|
||||
BOOST_ASIO_HANDLER_TYPE(ReadHandler, void(error_code, std::size_t))>{
|
||||
init.completion_handler, stream, buffer, parser}();
|
||||
return init.result.get();
|
||||
}
|
||||
@ -661,7 +642,8 @@ read(
|
||||
{
|
||||
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
||||
"SyncReadStream requirements not met");
|
||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||
static_assert(
|
||||
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||
"DynamicBuffer requirements not met");
|
||||
error_code ec;
|
||||
auto const bytes_transferred =
|
||||
@ -684,7 +666,8 @@ read(
|
||||
{
|
||||
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
||||
"SyncReadStream requirements not met");
|
||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||
static_assert(
|
||||
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||
"DynamicBuffer requirements not met");
|
||||
parser.eager(true);
|
||||
if(parser.is_done())
|
||||
@ -709,9 +692,8 @@ template<
|
||||
class DynamicBuffer,
|
||||
bool isRequest, class Derived,
|
||||
class ReadHandler>
|
||||
async_return_type<
|
||||
ReadHandler,
|
||||
void(error_code, std::size_t)>
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||
ReadHandler, void(error_code, std::size_t))
|
||||
async_read(
|
||||
AsyncReadStream& stream,
|
||||
DynamicBuffer& buffer,
|
||||
@ -720,15 +702,16 @@ async_read(
|
||||
{
|
||||
static_assert(is_async_read_stream<AsyncReadStream>::value,
|
||||
"AsyncReadStream requirements not met");
|
||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||
static_assert(
|
||||
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||
"DynamicBuffer requirements not met");
|
||||
parser.eager(true);
|
||||
async_completion<
|
||||
boost::asio::async_completion<
|
||||
ReadHandler,
|
||||
void(error_code, std::size_t)> init{handler};
|
||||
detail::read_op<AsyncReadStream, DynamicBuffer,
|
||||
isRequest, Derived, detail::parser_is_done,
|
||||
handler_type<ReadHandler, void(error_code, std::size_t)>>{
|
||||
BOOST_ASIO_HANDLER_TYPE(ReadHandler, void(error_code, std::size_t))>{
|
||||
init.completion_handler, stream, buffer, parser}();
|
||||
return init.result.get();
|
||||
}
|
||||
@ -747,7 +730,8 @@ read(
|
||||
{
|
||||
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
||||
"SyncReadStream requirements not met");
|
||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||
static_assert(
|
||||
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||
"DynamicBuffer requirements not met");
|
||||
static_assert(is_body<Body>::value,
|
||||
"Body requirements not met");
|
||||
@ -774,7 +758,8 @@ read(
|
||||
{
|
||||
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
||||
"SyncReadStream requirements not met");
|
||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||
static_assert(
|
||||
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||
"DynamicBuffer requirements not met");
|
||||
static_assert(is_body<Body>::value,
|
||||
"Body requirements not met");
|
||||
@ -795,9 +780,8 @@ template<
|
||||
class DynamicBuffer,
|
||||
bool isRequest, class Body, class Allocator,
|
||||
class ReadHandler>
|
||||
async_return_type<
|
||||
ReadHandler,
|
||||
void(error_code, std::size_t)>
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||
ReadHandler, void(error_code, std::size_t))
|
||||
async_read(
|
||||
AsyncReadStream& stream,
|
||||
DynamicBuffer& buffer,
|
||||
@ -806,21 +790,22 @@ async_read(
|
||||
{
|
||||
static_assert(is_async_read_stream<AsyncReadStream>::value,
|
||||
"AsyncReadStream requirements not met");
|
||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||
static_assert(
|
||||
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||
"DynamicBuffer requirements not met");
|
||||
static_assert(is_body<Body>::value,
|
||||
"Body requirements not met");
|
||||
static_assert(is_body_writer<Body>::value,
|
||||
"BodyWriter requirements not met");
|
||||
async_completion<
|
||||
boost::asio::async_completion<
|
||||
ReadHandler,
|
||||
void(error_code, std::size_t)> init{handler};
|
||||
detail::read_msg_op<
|
||||
AsyncReadStream,
|
||||
DynamicBuffer,
|
||||
isRequest, Body, Allocator,
|
||||
handler_type<ReadHandler,
|
||||
void(error_code, std::size_t)>>{
|
||||
BOOST_ASIO_HANDLER_TYPE(
|
||||
ReadHandler, void(error_code, std::size_t))>{
|
||||
init.completion_handler, stream, buffer, msg}();
|
||||
return init.result.get();
|
||||
}
|
||||
|
@ -166,12 +166,12 @@ next(error_code& ec, Visit&& visit)
|
||||
boost::in_place_init,
|
||||
frd_->get(),
|
||||
buffer_size(result->first),
|
||||
boost::asio::const_buffers_1{nullptr, 0},
|
||||
boost::asio::const_buffer{nullptr, 0},
|
||||
chunk_crlf{},
|
||||
result->first,
|
||||
chunk_crlf{},
|
||||
detail::chunk_last(),
|
||||
boost::asio::const_buffers_1{nullptr, 0},
|
||||
boost::asio::const_buffer{nullptr, 0},
|
||||
chunk_crlf{});
|
||||
goto go_all_c;
|
||||
}
|
||||
@ -179,7 +179,7 @@ next(error_code& ec, Visit&& visit)
|
||||
boost::in_place_init,
|
||||
frd_->get(),
|
||||
buffer_size(result->first),
|
||||
boost::asio::const_buffers_1{nullptr, 0},
|
||||
boost::asio::const_buffer{nullptr, 0},
|
||||
chunk_crlf{},
|
||||
result->first,
|
||||
chunk_crlf{});
|
||||
@ -216,19 +216,19 @@ next(error_code& ec, Visit&& visit)
|
||||
v_.template emplace<6>(
|
||||
boost::in_place_init,
|
||||
buffer_size(result->first),
|
||||
boost::asio::const_buffers_1{nullptr, 0},
|
||||
boost::asio::const_buffer{nullptr, 0},
|
||||
chunk_crlf{},
|
||||
result->first,
|
||||
chunk_crlf{},
|
||||
detail::chunk_last(),
|
||||
boost::asio::const_buffers_1{nullptr, 0},
|
||||
boost::asio::const_buffer{nullptr, 0},
|
||||
chunk_crlf{});
|
||||
goto go_body_final_c;
|
||||
}
|
||||
v_.template emplace<5>(
|
||||
boost::in_place_init,
|
||||
buffer_size(result->first),
|
||||
boost::asio::const_buffers_1{nullptr, 0},
|
||||
boost::asio::const_buffer{nullptr, 0},
|
||||
chunk_crlf{},
|
||||
result->first,
|
||||
chunk_crlf{});
|
||||
@ -257,7 +257,7 @@ next(error_code& ec, Visit&& visit)
|
||||
v_.template emplace<8>(
|
||||
boost::in_place_init,
|
||||
detail::chunk_last(),
|
||||
boost::asio::const_buffers_1{nullptr, 0},
|
||||
boost::asio::const_buffer{nullptr, 0},
|
||||
chunk_crlf{});
|
||||
s_ = do_final_c + 1;
|
||||
BOOST_BEAST_FALLTHROUGH;
|
||||
|
@ -16,9 +16,10 @@
|
||||
#include <boost/beast/core/handler_ptr.hpp>
|
||||
#include <boost/beast/core/type_traits.hpp>
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/asio/handler_alloc_hook.hpp>
|
||||
#include <boost/asio/associated_allocator.hpp>
|
||||
#include <boost/asio/associated_executor.hpp>
|
||||
#include <boost/asio/handler_continuation_hook.hpp>
|
||||
#include <boost/asio/handler_invoke_hook.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/asio/write.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
@ -77,6 +78,24 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
using allocator_type =
|
||||
boost::asio::associated_allocator_t<Handler>;
|
||||
|
||||
allocator_type
|
||||
get_allocator() const noexcept
|
||||
{
|
||||
return boost::asio::get_associated_allocator(h_);
|
||||
}
|
||||
|
||||
using executor_type = boost::asio::associated_executor_t<
|
||||
Handler, decltype(s_.get_executor())>;
|
||||
|
||||
executor_type get_executor() const noexcept
|
||||
{
|
||||
return boost::asio::get_associated_executor(
|
||||
h_, s_.get_executor());
|
||||
}
|
||||
|
||||
void
|
||||
operator()();
|
||||
|
||||
@ -85,24 +104,6 @@ public:
|
||||
error_code ec,
|
||||
std::size_t bytes_transferred);
|
||||
|
||||
friend
|
||||
void* asio_handler_allocate(
|
||||
std::size_t size, write_some_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_allocate;
|
||||
return asio_handler_allocate(
|
||||
size, std::addressof(op->h_));
|
||||
}
|
||||
|
||||
friend
|
||||
void asio_handler_deallocate(
|
||||
void* p, std::size_t size, write_some_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
asio_handler_deallocate(
|
||||
p, size, std::addressof(op->h_));
|
||||
}
|
||||
|
||||
friend
|
||||
bool asio_handler_is_continuation(write_some_op* op)
|
||||
{
|
||||
@ -110,14 +111,6 @@ public:
|
||||
return asio_handler_is_continuation(
|
||||
std::addressof(op->h_));
|
||||
}
|
||||
|
||||
template<class Function>
|
||||
friend
|
||||
void asio_handler_invoke(Function&& f, write_some_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_invoke;
|
||||
asio_handler_invoke(f, std::addressof(op->h_));
|
||||
}
|
||||
};
|
||||
|
||||
template<
|
||||
@ -136,7 +129,8 @@ operator()()
|
||||
if(ec)
|
||||
{
|
||||
BOOST_ASSERT(! f.invoked);
|
||||
return s_.get_io_service().post(
|
||||
return boost::asio::post(
|
||||
s_.get_executor(),
|
||||
bind_handler(std::move(*this), ec, 0));
|
||||
}
|
||||
if(f.invoked)
|
||||
@ -148,7 +142,8 @@ operator()()
|
||||
// What else could it be?
|
||||
BOOST_ASSERT(sr_.is_done());
|
||||
}
|
||||
return s_.get_io_service().post(
|
||||
return boost::asio::post(
|
||||
s_.get_executor(),
|
||||
bind_handler(std::move(*this), ec, 0));
|
||||
}
|
||||
|
||||
@ -218,29 +213,29 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
using allocator_type =
|
||||
boost::asio::associated_allocator_t<Handler>;
|
||||
|
||||
allocator_type
|
||||
get_allocator() const noexcept
|
||||
{
|
||||
return boost::asio::get_associated_allocator(h_);
|
||||
}
|
||||
|
||||
using executor_type = boost::asio::associated_executor_t<
|
||||
Handler, decltype(s_.get_executor())>;
|
||||
|
||||
executor_type get_executor() const noexcept
|
||||
{
|
||||
return boost::asio::get_associated_executor(
|
||||
h_, s_.get_executor());
|
||||
}
|
||||
|
||||
void
|
||||
operator()(
|
||||
error_code ec = {},
|
||||
std::size_t bytes_transferred = 0);
|
||||
|
||||
friend
|
||||
void* asio_handler_allocate(
|
||||
std::size_t size, write_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_allocate;
|
||||
return asio_handler_allocate(
|
||||
size, std::addressof(op->h_));
|
||||
}
|
||||
|
||||
friend
|
||||
void asio_handler_deallocate(
|
||||
void* p, std::size_t size, write_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
asio_handler_deallocate(
|
||||
p, size, std::addressof(op->h_));
|
||||
}
|
||||
|
||||
friend
|
||||
bool asio_handler_is_continuation(write_op* op)
|
||||
{
|
||||
@ -249,15 +244,6 @@ public:
|
||||
asio_handler_is_continuation(
|
||||
std::addressof(op->h_));
|
||||
}
|
||||
|
||||
template<class Function>
|
||||
friend
|
||||
void asio_handler_invoke(Function&& f, write_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_invoke;
|
||||
asio_handler_invoke(
|
||||
f, std::addressof(op->h_));
|
||||
}
|
||||
};
|
||||
|
||||
template<
|
||||
@ -278,7 +264,8 @@ operator()(
|
||||
if(Predicate{}(sr_))
|
||||
{
|
||||
state_ = 1;
|
||||
return s_.get_io_service().post(
|
||||
return boost::asio::post(
|
||||
s_.get_executor(),
|
||||
bind_handler(std::move(*this), ec, 0));
|
||||
}
|
||||
state_ = 2;
|
||||
@ -338,6 +325,24 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
using allocator_type =
|
||||
boost::asio::associated_allocator_t<Handler>;
|
||||
|
||||
allocator_type
|
||||
get_allocator() const noexcept
|
||||
{
|
||||
return boost::asio::get_associated_allocator(d_.handler());
|
||||
}
|
||||
|
||||
using executor_type = boost::asio::associated_executor_t<
|
||||
Handler, decltype(d_->s.get_executor())>;
|
||||
|
||||
executor_type get_executor() const noexcept
|
||||
{
|
||||
return boost::asio::get_associated_executor(
|
||||
d_.handler(), d_->s.get_executor());
|
||||
}
|
||||
|
||||
void
|
||||
operator()();
|
||||
|
||||
@ -345,24 +350,6 @@ public:
|
||||
operator()(
|
||||
error_code ec, std::size_t bytes_transferred);
|
||||
|
||||
friend
|
||||
void* asio_handler_allocate(
|
||||
std::size_t size, write_msg_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_allocate;
|
||||
return asio_handler_allocate(
|
||||
size, std::addressof(op->d_.handler()));
|
||||
}
|
||||
|
||||
friend
|
||||
void asio_handler_deallocate(
|
||||
void* p, std::size_t size, write_msg_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
asio_handler_deallocate(
|
||||
p, size, std::addressof(op->d_.handler()));
|
||||
}
|
||||
|
||||
friend
|
||||
bool asio_handler_is_continuation(write_msg_op* op)
|
||||
{
|
||||
@ -370,15 +357,6 @@ public:
|
||||
return asio_handler_is_continuation(
|
||||
std::addressof(op->d_.handler()));
|
||||
}
|
||||
|
||||
template<class Function>
|
||||
friend
|
||||
void asio_handler_invoke(Function&& f, write_msg_op* op)
|
||||
{
|
||||
using boost::asio::asio_handler_invoke;
|
||||
asio_handler_invoke(
|
||||
f, std::addressof(op->d_.handler()));
|
||||
}
|
||||
};
|
||||
|
||||
template<class Stream, class Handler,
|
||||
@ -483,21 +461,20 @@ template<
|
||||
class AsyncWriteStream,
|
||||
bool isRequest, class Body, class Fields,
|
||||
class WriteHandler>
|
||||
async_return_type<
|
||||
WriteHandler,
|
||||
void(error_code, std::size_t)>
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||
WriteHandler, void(error_code, std::size_t))
|
||||
async_write_some(
|
||||
AsyncWriteStream& stream,
|
||||
serializer<isRequest, Body, Fields>& sr,
|
||||
WriteHandler&& handler)
|
||||
{
|
||||
async_completion<
|
||||
boost::asio::async_completion<
|
||||
WriteHandler,
|
||||
void(error_code, std::size_t)> init{handler};
|
||||
detail::write_some_op<
|
||||
AsyncWriteStream,
|
||||
handler_type<WriteHandler,
|
||||
void(error_code, std::size_t)>,
|
||||
BOOST_ASIO_HANDLER_TYPE(WriteHandler,
|
||||
void(error_code, std::size_t)),
|
||||
isRequest, Body, Fields>{
|
||||
init.completion_handler, stream, sr}();
|
||||
return init.result.get();
|
||||
@ -551,9 +528,8 @@ template<
|
||||
class AsyncWriteStream,
|
||||
bool isRequest, class Body, class Fields,
|
||||
class WriteHandler>
|
||||
async_return_type<
|
||||
WriteHandler,
|
||||
void(error_code, std::size_t)>
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||
WriteHandler, void(error_code, std::size_t))
|
||||
async_write_some(
|
||||
AsyncWriteStream& stream,
|
||||
serializer<isRequest, Body, Fields>& sr,
|
||||
@ -635,9 +611,8 @@ template<
|
||||
class AsyncWriteStream,
|
||||
bool isRequest, class Body, class Fields,
|
||||
class WriteHandler>
|
||||
async_return_type<
|
||||
WriteHandler,
|
||||
void(error_code, std::size_t)>
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||
WriteHandler, void(error_code, std::size_t))
|
||||
async_write_header(
|
||||
AsyncWriteStream& stream,
|
||||
serializer<isRequest, Body, Fields>& sr,
|
||||
@ -651,13 +626,13 @@ async_write_header(
|
||||
static_assert(is_body_reader<Body>::value,
|
||||
"BodyReader requirements not met");
|
||||
sr.split(true);
|
||||
async_completion<
|
||||
boost::asio::async_completion<
|
||||
WriteHandler,
|
||||
void(error_code, std::size_t)> init{handler};
|
||||
detail::write_op<
|
||||
AsyncWriteStream,
|
||||
handler_type<WriteHandler,
|
||||
void(error_code, std::size_t)>,
|
||||
BOOST_ASIO_HANDLER_TYPE(WriteHandler,
|
||||
void(error_code, std::size_t)),
|
||||
detail::serializer_is_header_done,
|
||||
isRequest, Body, Fields>{
|
||||
init.completion_handler, stream, sr}();
|
||||
@ -713,9 +688,8 @@ template<
|
||||
class AsyncWriteStream,
|
||||
bool isRequest, class Body, class Fields,
|
||||
class WriteHandler>
|
||||
async_return_type<
|
||||
WriteHandler,
|
||||
void(error_code, std::size_t)>
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||
WriteHandler, void(error_code, std::size_t))
|
||||
async_write(
|
||||
AsyncWriteStream& stream,
|
||||
serializer<isRequest, Body, Fields>& sr,
|
||||
@ -729,13 +703,13 @@ async_write(
|
||||
static_assert(is_body_reader<Body>::value,
|
||||
"BodyReader requirements not met");
|
||||
sr.split(false);
|
||||
async_completion<
|
||||
boost::asio::async_completion<
|
||||
WriteHandler,
|
||||
void(error_code, std::size_t)> init{handler};
|
||||
detail::write_op<
|
||||
AsyncWriteStream,
|
||||
handler_type<WriteHandler,
|
||||
void(error_code, std::size_t)>,
|
||||
BOOST_ASIO_HANDLER_TYPE(WriteHandler,
|
||||
void(error_code, std::size_t)),
|
||||
detail::serializer_is_done,
|
||||
isRequest, Body, Fields>{
|
||||
init.completion_handler, stream, sr}();
|
||||
@ -789,9 +763,8 @@ template<
|
||||
class AsyncWriteStream,
|
||||
bool isRequest, class Body, class Fields,
|
||||
class WriteHandler>
|
||||
async_return_type<
|
||||
WriteHandler,
|
||||
void(error_code, std::size_t)>
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||
WriteHandler, void(error_code, std::size_t))
|
||||
async_write(
|
||||
AsyncWriteStream& stream,
|
||||
message<isRequest, Body, Fields>& msg,
|
||||
@ -804,13 +777,13 @@ async_write(
|
||||
"Body requirements not met");
|
||||
static_assert(is_body_reader<Body>::value,
|
||||
"BodyReader requirements not met");
|
||||
async_completion<
|
||||
boost::asio::async_completion<
|
||||
WriteHandler,
|
||||
void(error_code, std::size_t)> init{handler};
|
||||
detail::write_msg_op<
|
||||
AsyncWriteStream,
|
||||
handler_type<WriteHandler,
|
||||
void(error_code, std::size_t)>,
|
||||
BOOST_ASIO_HANDLER_TYPE(WriteHandler,
|
||||
void(error_code, std::size_t)),
|
||||
isRequest, Body, Fields>{
|
||||
init.completion_handler, stream, msg}();
|
||||
return init.result.get();
|
||||
@ -843,17 +816,13 @@ public:
|
||||
if(os_.fail())
|
||||
return;
|
||||
std::size_t bytes_transferred = 0;
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
for(auto it = buffers.begin();
|
||||
it != buffers.end(); ++it)
|
||||
for(auto b : buffers_range(buffers))
|
||||
{
|
||||
boost::asio::const_buffer b = *it;
|
||||
auto const n = buffer_size(b);
|
||||
os_.write(buffer_cast<char const*>(b), n);
|
||||
os_.write(reinterpret_cast<char const*>(
|
||||
b.data()), b.size());
|
||||
if(os_.fail())
|
||||
return;
|
||||
bytes_transferred += n;
|
||||
bytes_transferred += b.size();
|
||||
}
|
||||
sr_.consume(bytes_transferred);
|
||||
}
|
||||
|
@ -11,10 +11,10 @@
|
||||
#define BOOST_BEAST_HTTP_READ_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/beast/core/async_result.hpp>
|
||||
#include <boost/beast/core/error.hpp>
|
||||
#include <boost/beast/http/basic_parser.hpp>
|
||||
#include <boost/beast/http/message.hpp>
|
||||
#include <boost/asio/async_result.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
@ -185,7 +185,7 @@ read_some(
|
||||
Regardless of whether the asynchronous operation completes
|
||||
immediately or not, the handler will not be invoked from within
|
||||
this function. Invocation of the handler will be performed in a
|
||||
manner equivalent to using `boost::asio::io_service::post`.
|
||||
manner equivalent to using `boost::asio::io_context::post`.
|
||||
|
||||
The completion handler will receive as a parameter the number
|
||||
of octets processed from the dynamic buffer. The octets should
|
||||
@ -197,12 +197,8 @@ template<
|
||||
class DynamicBuffer,
|
||||
bool isRequest, class Derived,
|
||||
class ReadHandler>
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
void_or_deduced
|
||||
#else
|
||||
async_return_type<
|
||||
ReadHandler, void(error_code, std::size_t)>
|
||||
#endif
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||
ReadHandler, void(error_code, std::size_t))
|
||||
async_read_some(
|
||||
AsyncReadStream& stream,
|
||||
DynamicBuffer& buffer,
|
||||
@ -375,7 +371,7 @@ read_header(
|
||||
Regardless of whether the asynchronous operation completes
|
||||
immediately or not, the handler will not be invoked from within
|
||||
this function. Invocation of the handler will be performed in a
|
||||
manner equivalent to using `boost::asio::io_service::post`.
|
||||
manner equivalent to using `boost::asio::io_context::post`.
|
||||
|
||||
@note The implementation will call @ref basic_parser::eager
|
||||
with the value `false` on the parser passed in.
|
||||
@ -385,12 +381,8 @@ template<
|
||||
class DynamicBuffer,
|
||||
bool isRequest, class Derived,
|
||||
class ReadHandler>
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
void_or_deduced
|
||||
#else
|
||||
async_return_type<
|
||||
ReadHandler, void(error_code, std::size_t)>
|
||||
#endif
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||
ReadHandler, void(error_code, std::size_t))
|
||||
async_read_header(
|
||||
AsyncReadStream& stream,
|
||||
DynamicBuffer& buffer,
|
||||
@ -563,7 +555,7 @@ read(
|
||||
Regardless of whether the asynchronous operation completes
|
||||
immediately or not, the handler will not be invoked from within
|
||||
this function. Invocation of the handler will be performed in a
|
||||
manner equivalent to using `boost::asio::io_service::post`.
|
||||
manner equivalent to using `boost::asio::io_context::post`.
|
||||
|
||||
@note The implementation will call @ref basic_parser::eager
|
||||
with the value `true` on the parser passed in.
|
||||
@ -573,13 +565,8 @@ template<
|
||||
class DynamicBuffer,
|
||||
bool isRequest, class Derived,
|
||||
class ReadHandler>
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
void_or_deduced
|
||||
#else
|
||||
async_return_type<
|
||||
ReadHandler,
|
||||
void(error_code, std::size_t)>
|
||||
#endif
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||
ReadHandler, void(error_code, std::size_t))
|
||||
async_read(
|
||||
AsyncReadStream& stream,
|
||||
DynamicBuffer& buffer,
|
||||
@ -754,20 +741,15 @@ read(
|
||||
Regardless of whether the asynchronous operation completes
|
||||
immediately or not, the handler will not be invoked from within
|
||||
this function. Invocation of the handler will be performed in a
|
||||
manner equivalent to using `boost::asio::io_service::post`.
|
||||
manner equivalent to using `boost::asio::io_context::post`.
|
||||
*/
|
||||
template<
|
||||
class AsyncReadStream,
|
||||
class DynamicBuffer,
|
||||
bool isRequest, class Body, class Allocator,
|
||||
class ReadHandler>
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
void_or_deduced
|
||||
#else
|
||||
async_return_type<
|
||||
ReadHandler,
|
||||
void(error_code, std::size_t)>
|
||||
#endif
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||
ReadHandler, void(error_code, std::size_t))
|
||||
async_read(
|
||||
AsyncReadStream& stream,
|
||||
DynamicBuffer& buffer,
|
||||
|
@ -132,7 +132,7 @@ private:
|
||||
using cb4_t = buffers_suffix<buffers_cat_view<
|
||||
typename Fields::reader::const_buffers_type,// header
|
||||
detail::chunk_size, // chunk-size
|
||||
boost::asio::const_buffers_1, // chunk-ext
|
||||
boost::asio::const_buffer, // chunk-ext
|
||||
chunk_crlf, // crlf
|
||||
typename reader::const_buffers_type, // body
|
||||
chunk_crlf>>; // crlf
|
||||
@ -140,7 +140,7 @@ private:
|
||||
|
||||
using cb5_t = buffers_suffix<buffers_cat_view<
|
||||
detail::chunk_size, // chunk-header
|
||||
boost::asio::const_buffers_1, // chunk-ext
|
||||
boost::asio::const_buffer, // chunk-ext
|
||||
chunk_crlf, // crlf
|
||||
typename reader::const_buffers_type, // body
|
||||
chunk_crlf>>; // crlf
|
||||
@ -148,30 +148,30 @@ private:
|
||||
|
||||
using cb6_t = buffers_suffix<buffers_cat_view<
|
||||
detail::chunk_size, // chunk-header
|
||||
boost::asio::const_buffers_1, // chunk-size
|
||||
boost::asio::const_buffer, // chunk-size
|
||||
chunk_crlf, // crlf
|
||||
typename reader::const_buffers_type, // body
|
||||
chunk_crlf, // crlf
|
||||
boost::asio::const_buffers_1, // chunk-final
|
||||
boost::asio::const_buffers_1, // trailers
|
||||
boost::asio::const_buffer, // chunk-final
|
||||
boost::asio::const_buffer, // trailers
|
||||
chunk_crlf>>; // crlf
|
||||
using pcb6_t = buffers_prefix_view<cb6_t const&>;
|
||||
|
||||
using cb7_t = buffers_suffix<buffers_cat_view<
|
||||
typename Fields::reader::const_buffers_type,// header
|
||||
detail::chunk_size, // chunk-size
|
||||
boost::asio::const_buffers_1, // chunk-ext
|
||||
boost::asio::const_buffer, // chunk-ext
|
||||
chunk_crlf, // crlf
|
||||
typename reader::const_buffers_type, // body
|
||||
chunk_crlf, // crlf
|
||||
boost::asio::const_buffers_1, // chunk-final
|
||||
boost::asio::const_buffers_1, // trailers
|
||||
boost::asio::const_buffer, // chunk-final
|
||||
boost::asio::const_buffer, // trailers
|
||||
chunk_crlf>>; // crlf
|
||||
using pcb7_t = buffers_prefix_view<cb7_t const&>;
|
||||
|
||||
using cb8_t = buffers_suffix<buffers_cat_view<
|
||||
boost::asio::const_buffers_1, // chunk-final
|
||||
boost::asio::const_buffers_1, // trailers
|
||||
boost::asio::const_buffer, // chunk-final
|
||||
boost::asio::const_buffer, // trailers
|
||||
chunk_crlf>>; // crlf
|
||||
using pcb8_t = buffers_prefix_view<cb8_t const&>;
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user