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:
|
Version 124:
|
||||||
|
|
||||||
* Fix for a test matrix compiler
|
* Fix for a test matrix compiler
|
||||||
|
@ -21,7 +21,6 @@ if (MSVC)
|
|||||||
add_definitions (-D_WIN32_WINNT=0x0601)
|
add_definitions (-D_WIN32_WINNT=0x0601)
|
||||||
add_definitions (-D_SCL_SECURE_NO_WARNINGS=1)
|
add_definitions (-D_SCL_SECURE_NO_WARNINGS=1)
|
||||||
add_definitions (-D_CRT_SECURE_NO_WARNINGS=1)
|
add_definitions (-D_CRT_SECURE_NO_WARNINGS=1)
|
||||||
add_definitions (-DBOOST_ASIO_NO_DEPRECATED=1)
|
|
||||||
|
|
||||||
add_compile_options(
|
add_compile_options(
|
||||||
/bigobj # large object file format
|
/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
|
# VFALCO I want static but "b2 stage" builds a minimal set which excludes static
|
||||||
add_definitions (-DBOOST_ALL_STATIC_LINK=1)
|
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_ARRAY=1)
|
||||||
add_definitions (-DBOOST_ASIO_DISABLE_BOOST_BIND=1)
|
add_definitions (-DBOOST_ASIO_DISABLE_BOOST_BIND=1)
|
||||||
add_definitions (-DBOOST_ASIO_DISABLE_BOOST_DATE_TIME=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_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 __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 __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 __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`]]
|
[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
|
[table Global Variables
|
||||||
[[Name][Description]]
|
[[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
|
A variable of type
|
||||||
[@http://www.boost.org/doc/html/boost_asio/reference/io_service.html `boost::asio::io_service`]
|
[@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 a
|
which is running on one separate thread, and upon which an
|
||||||
[@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/executor_work.html `boost::asio::executor_work`]
|
||||||
object has been constructed.
|
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`.
|
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,
|
Determine if the `get_executor` member function is present.
|
||||||
and returns an __io_service__.
|
|
||||||
]]
|
]]
|
||||||
[[
|
[[
|
||||||
[link beast.ref.boost__beast__is_async_read_stream `is_async_read_stream`]
|
[link beast.ref.boost__beast__is_async_read_stream `is_async_read_stream`]
|
||||||
|
@ -9,36 +9,71 @@
|
|||||||
|
|
||||||
[section Buffer Types]
|
[section Buffer Types]
|
||||||
|
|
||||||
__Asio__ provides the __ConstBufferSequence__ and __MutableBufferSequence__
|
To facilitate working with instances of the __ConstBufferSequence__ and
|
||||||
concepts, whose models provide ranges of buffers, as well as the __streambuf__
|
__MutableBufferSequence__ concepts introduced in __Asio__, Beast treats
|
||||||
class which encapsulates memory storage that may be automatically resized as
|
those sequences as a special type of range. The following algorithms and
|
||||||
required, where the memory is divided into an input sequence followed by an
|
wrappers are provided which transform these ranges efficiently using lazy
|
||||||
output sequence. The Networking TS (__N4588__) generalizes this `streambuf`
|
evaluation. No memory allocations are used in the transformations; instead,
|
||||||
interface into the __DynamicBuffer__ concept. Beast algorithms which require
|
they create lightweight iterators over the existing, unmodified memory
|
||||||
resizable buffers accept dynamic buffer objects as templated parameters.
|
buffers. Control of buffers is retained by the caller; ownership is not
|
||||||
These metafunctions check if types match the buffer concepts:
|
transferred.
|
||||||
|
|
||||||
[table Buffer Type Checks
|
[table Buffer Algorithms and Types
|
||||||
[[Name][Description]]
|
[[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
|
The __DynamicBuffer__ concept introduced in __Asio__ models a buffer
|
||||||
of scenarios:
|
sequence which supports an owning, resizable range. Beast provides this
|
||||||
|
set of additional implementations of the dynamic buffer concept:
|
||||||
|
|
||||||
[table Dynamic Buffer Implementations
|
[table Dynamic Buffer Implementations
|
||||||
[[Name][Description]]
|
[[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
|
These two functions facilitate buffer interoperability with standard
|
||||||
output streams.
|
output streams.
|
||||||
|
|
||||||
|
@ -38,23 +38,6 @@ composed operations:
|
|||||||
|
|
||||||
[table Asynchronous Helpers
|
[table Asynchronous Helpers
|
||||||
[[Name][Description]]
|
[[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`]
|
[link beast.ref.boost__beast__bind_handler `bind_handler`]
|
||||||
][
|
][
|
||||||
@ -66,15 +49,6 @@ composed operations:
|
|||||||
`asio_handler_invoke` associated with the original completion handler.
|
`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`]
|
[link beast.ref.boost__beast__handler_ptr `handler_ptr`]
|
||||||
][
|
][
|
||||||
@ -87,14 +61,6 @@ composed operations:
|
|||||||
associated allocator, benefiting from all handler memory management
|
associated allocator, benefiting from all handler memory management
|
||||||
optimizations transparently.
|
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.
|
* 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
|
* Forgetting to include a return statement after calling an
|
||||||
initiating function.
|
initiating function.
|
||||||
|
|
||||||
* Calling a synchronous function by accident. In general composed
|
* Calling a synchronous function by accident. In general composed
|
||||||
operations should not block for long periods of time, since this
|
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
|
* Forgetting to provide `executor_type` and `get_executor` for the
|
||||||
operation. This will cause undefined behavior if someone calls
|
composed operation. This will cause undefined behavior. For example,
|
||||||
the initiating function with a strand-wrapped function object,
|
if someone calls the initiating function with a strand-wrapped
|
||||||
and there is more than thread running on the `io_service`.
|
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
|
* 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
|
to invoke the final handler. This breaks the following initiating
|
||||||
function guarantee: ['Regardless of whether the asynchronous operation
|
function guarantee: ['Regardless of whether the asynchronous operation
|
||||||
completes immediately or not, the handler will not be invoked from
|
completes immediately or not, the handler will not be invoked from
|
||||||
within this function. Invocation of the handler will be performed
|
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
|
The function
|
||||||
[link beast.ref.boost__beast__bind_handler `bind_handler`]
|
[link beast.ref.boost__beast__bind_handler `bind_handler`]
|
||||||
is provided for this purpose.
|
is provided for this purpose.
|
||||||
|
@ -83,9 +83,9 @@ as this example shows.
|
|||||||
If a read stream algorithm cannot complete its operation without exceeding
|
If a read stream algorithm cannot complete its operation without exceeding
|
||||||
the maximum specified size of the dynamic buffer provided, the error
|
the maximum specified size of the dynamic buffer provided, the error
|
||||||
[link beast.ref.boost__beast__http__error `buffer_overflow`]
|
[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
|
is returned. This is one technique which may be used to impose a limit on
|
||||||
HTTP message header for protection from buffer overflow attacks. The
|
the maximum size of an HTTP message header for protection from buffer
|
||||||
following code will print the error message:
|
overflow attacks. The following code will print the error message:
|
||||||
|
|
||||||
[http_snippet_6]
|
[http_snippet_6]
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ field value.
|
|||||||
|
|
||||||
[heading Serializing Chunks]
|
[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
|
when a message returns `true` from
|
||||||
[link beast.ref.boost__beast__http__message.chunked.overload1 `message::chunked`].
|
[link beast.ref.boost__beast__http__message.chunked.overload1 `message::chunked`].
|
||||||
The boundaries between chunks emitted by the serializer are implementation
|
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.
|
the stream wrapper are passed to next layer's constructor.
|
||||||
|
|
||||||
Here we declare a websocket stream over a TCP/IP socket with ownership
|
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:
|
socket's constructor:
|
||||||
|
|
||||||
[ws_snippet_2]
|
[ws_snippet_2]
|
||||||
@ -27,7 +27,7 @@ socket's constructor:
|
|||||||
[heading Using SSL]
|
[heading Using SSL]
|
||||||
|
|
||||||
To use WebSockets over SSL, use an instance of the `boost::asio::ssl::stream`
|
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:
|
and `ssl::context` arguments are forwarded to the wrapped stream's constructor:
|
||||||
|
|
||||||
[wss_snippet_1]
|
[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
|
on the received HTTP response message. For example, to check that the
|
||||||
response to a basic authentication challenge is valid. To achieve this,
|
response to a basic authentication challenge is valid. To achieve this,
|
||||||
overloads of the handshake member function allow the caller to store the
|
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`]
|
[link beast.ref.boost__beast__websocket__response_type `response_type`]
|
||||||
as follows:
|
as follows:
|
||||||
|
|
||||||
|
@ -31,9 +31,12 @@ handlers, stackful or stackless coroutines, and even futures:
|
|||||||
|
|
||||||
[ws_snippet_21]
|
[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
|
underlying stream is left to the callers, permitting any implementation
|
||||||
strategy including one that does not require threads for environments
|
strategy including one that does not require threads for environments
|
||||||
where threads are unavailable. Beast WebSocket itself does not use
|
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`]
|
[link beast.ref.boost__beast__websocket__stream `stream`]
|
||||||
is not thread safe. Callers are responsible for synchronizing operations on
|
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 socket using an implicit or explicit strand, as per the Asio documentation.
|
||||||
The asynchronous interface supports one of each of the following operations
|
The websocket stream asynchronous interface supports one of each of the
|
||||||
to be active at the same time:
|
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_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`]
|
* [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]
|
[heading Associated Types]
|
||||||
|
|
||||||
* [link beast.ref.boost__beast__is_dynamic_buffer `is_dynamic_buffer`]
|
* `boost::asio::is_dynamic_buffer`
|
||||||
* __ConstBufferSequence__
|
* __ConstBufferSequence__
|
||||||
* __MutableBufferSequence__
|
* __MutableBufferSequence__
|
||||||
|
|
||||||
|
@ -190,7 +190,7 @@ In this table:
|
|||||||
[
|
[
|
||||||
If `(v < 11 && b)`, then all "close" tokens present in the
|
If `(v < 11 && b)`, then all "close" tokens present in the
|
||||||
value are removed, and the "keep-alive" token is added to
|
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"
|
If `(v < 11 && ! b)`, then all "close" and "keep-alive"
|
||||||
tokens present in the value are removed.
|
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
|
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
|
be optimal for interacting with Asio, and for other tasks such as incremental
|
||||||
parsing of data in buffers (for example, parsing websocket frames stored
|
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
|
During the development of Beast the authors have studied other software
|
||||||
packages and in particular the comments left during the Boost Review process
|
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
|
The start-line data members are replaced by traditional accessors
|
||||||
non-owning references to string buffers. The method is stored using
|
using non-owning references to string buffers. The method is stored
|
||||||
a simple integer instead of the entire string, for the case where
|
using a simple integer instead of the entire string, for the case
|
||||||
the method is recognized from the set of known verb strings.
|
where the method is recognized from the set of known verb strings.
|
||||||
|
|
||||||
Now we add a requirement to the fields type: management of the
|
Now we add a requirement to the fields type: management of the
|
||||||
corresponding string is delegated to the [*Fields] container, which can
|
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
|
The only requirement in Beast is that calls to asynchronous initiation
|
||||||
functions are made from the same implicit or explicit strand. For
|
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
|
is single threaded, this counts as an implicit strand and no performance
|
||||||
costs associated with mutexes are incurred.
|
costs associated with mutexes are incurred.
|
||||||
|
|
||||||
|
@ -174,9 +174,6 @@
|
|||||||
<entry valign="top">
|
<entry valign="top">
|
||||||
<bridgehead renderas="sect3">Classes</bridgehead>
|
<bridgehead renderas="sect3">Classes</bridgehead>
|
||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
<member><link linkend="beast.ref.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_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__basic_multi_buffer">basic_multi_buffer</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__buffered_read_stream">buffered_read_stream</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_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">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__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_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__iequal">iequal</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__iless">iless</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>
|
<member><link linkend="beast.ref.boost__beast__multi_buffer">multi_buffer</link></member>
|
||||||
@ -236,15 +231,12 @@
|
|||||||
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
<member><link linkend="beast.ref.boost__beast__get_lowest_layer">get_lowest_layer</link></member>
|
<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_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_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_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_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_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_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_stream">is_sync_stream</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__is_sync_write_stream">is_sync_write_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 = \
|
PREDEFINED = \
|
||||||
BOOST_BEAST_DOXYGEN \
|
BOOST_BEAST_DOXYGEN \
|
||||||
BOOST_BEAST_USE_POSIX_FILE=1 \
|
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 =
|
EXPAND_AS_DEFINED =
|
||||||
SKIP_FUNCTION_MACROS = YES
|
SKIP_FUNCTION_MACROS = YES
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <boost/beast/http.hpp>
|
#include <boost/beast/http.hpp>
|
||||||
#include <boost/beast/websocket.hpp>
|
#include <boost/beast/websocket.hpp>
|
||||||
#include <boost/beast/version.hpp>
|
#include <boost/beast/version.hpp>
|
||||||
|
#include <boost/asio/bind_executor.hpp>
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
#include <boost/asio/ssl/stream.hpp>
|
#include <boost/asio/ssl/stream.hpp>
|
||||||
#include <boost/asio/strand.hpp>
|
#include <boost/asio/strand.hpp>
|
||||||
@ -235,15 +236,16 @@ class websocket_session
|
|||||||
boost::beast::multi_buffer buffer_;
|
boost::beast::multi_buffer buffer_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
boost::asio::io_service::strand strand_;
|
boost::asio::strand<
|
||||||
|
boost::asio::io_context::executor_type> strand_;
|
||||||
boost::asio::steady_timer timer_;
|
boost::asio::steady_timer timer_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Construct the session
|
// Construct the session
|
||||||
explicit
|
explicit
|
||||||
websocket_session(boost::asio::io_service& ios)
|
websocket_session(boost::asio::io_context& ioc)
|
||||||
: strand_(ios)
|
: strand_(ioc.get_executor())
|
||||||
, timer_(ios,
|
, timer_(ioc,
|
||||||
(std::chrono::steady_clock::time_point::max)())
|
(std::chrono::steady_clock::time_point::max)())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -254,15 +256,17 @@ public:
|
|||||||
do_accept(http::request<Body, http::basic_fields<Allocator>> req)
|
do_accept(http::request<Body, http::basic_fields<Allocator>> req)
|
||||||
{
|
{
|
||||||
// Set the timer
|
// Set the timer
|
||||||
timer_.expires_from_now(std::chrono::seconds(15));
|
timer_.expires_after(std::chrono::seconds(15));
|
||||||
|
|
||||||
// Accept the websocket handshake
|
// Accept the websocket handshake
|
||||||
derived().ws().async_accept(
|
derived().ws().async_accept(
|
||||||
req,
|
req,
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&websocket_session::on_accept,
|
strand_,
|
||||||
derived().shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1)));
|
&websocket_session::on_accept,
|
||||||
|
derived().shared_from_this(),
|
||||||
|
std::placeholders::_1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when the timer expires.
|
// Called when the timer expires.
|
||||||
@ -273,15 +277,17 @@ public:
|
|||||||
return fail(ec, "timer");
|
return fail(ec, "timer");
|
||||||
|
|
||||||
// Verify that the timer really expired since the deadline may have moved.
|
// 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();
|
derived().do_timeout();
|
||||||
|
|
||||||
// Wait on the timer
|
// Wait on the timer
|
||||||
timer_.async_wait(
|
timer_.async_wait(
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&websocket_session::on_timer,
|
strand_,
|
||||||
derived().shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1)));
|
&websocket_session::on_timer,
|
||||||
|
derived().shared_from_this(),
|
||||||
|
std::placeholders::_1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -302,16 +308,18 @@ public:
|
|||||||
do_read()
|
do_read()
|
||||||
{
|
{
|
||||||
// Set the timer
|
// Set the timer
|
||||||
timer_.expires_from_now(std::chrono::seconds(15));
|
timer_.expires_after(std::chrono::seconds(15));
|
||||||
|
|
||||||
// Read a message into our buffer
|
// Read a message into our buffer
|
||||||
derived().ws().async_read(
|
derived().ws().async_read(
|
||||||
buffer_,
|
buffer_,
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&websocket_session::on_read,
|
strand_,
|
||||||
derived().shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&websocket_session::on_read,
|
||||||
std::placeholders::_2)));
|
derived().shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -336,11 +344,13 @@ public:
|
|||||||
derived().ws().text(derived().ws().got_text());
|
derived().ws().text(derived().ws().got_text());
|
||||||
derived().ws().async_write(
|
derived().ws().async_write(
|
||||||
buffer_.data(),
|
buffer_.data(),
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&websocket_session::on_write,
|
strand_,
|
||||||
derived().shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&websocket_session::on_write,
|
||||||
std::placeholders::_2)));
|
derived().shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -378,7 +388,7 @@ public:
|
|||||||
explicit
|
explicit
|
||||||
plain_websocket_session(tcp::socket socket)
|
plain_websocket_session(tcp::socket socket)
|
||||||
: websocket_session<plain_websocket_session>(
|
: websocket_session<plain_websocket_session>(
|
||||||
socket.get_io_service())
|
socket.get_executor().context())
|
||||||
, ws_(std::move(socket))
|
, ws_(std::move(socket))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -412,15 +422,17 @@ public:
|
|||||||
close_ = true;
|
close_ = true;
|
||||||
|
|
||||||
// Set the timer
|
// Set the timer
|
||||||
timer_.expires_from_now(std::chrono::seconds(15));
|
timer_.expires_after(std::chrono::seconds(15));
|
||||||
|
|
||||||
// Close the WebSocket Connection
|
// Close the WebSocket Connection
|
||||||
ws_.async_close(
|
ws_.async_close(
|
||||||
websocket::close_code::normal,
|
websocket::close_code::normal,
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&plain_websocket_session::on_close,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1)));
|
&plain_websocket_session::on_close,
|
||||||
|
shared_from_this(),
|
||||||
|
std::placeholders::_1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -443,7 +455,8 @@ class ssl_websocket_session
|
|||||||
, public std::enable_shared_from_this<ssl_websocket_session>
|
, public std::enable_shared_from_this<ssl_websocket_session>
|
||||||
{
|
{
|
||||||
websocket::stream<ssl_stream<tcp::socket>> ws_;
|
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;
|
bool eof_ = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -451,9 +464,9 @@ public:
|
|||||||
explicit
|
explicit
|
||||||
ssl_websocket_session(ssl_stream<tcp::socket> stream)
|
ssl_websocket_session(ssl_stream<tcp::socket> stream)
|
||||||
: websocket_session<ssl_websocket_session>(
|
: websocket_session<ssl_websocket_session>(
|
||||||
stream.get_io_service())
|
stream.get_executor().context())
|
||||||
, ws_(std::move(stream))
|
, ws_(std::move(stream))
|
||||||
, strand_(ws_.get_io_service())
|
, strand_(ws_.get_executor())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -483,14 +496,16 @@ public:
|
|||||||
eof_ = true;
|
eof_ = true;
|
||||||
|
|
||||||
// Set the timer
|
// Set the timer
|
||||||
timer_.expires_from_now(std::chrono::seconds(15));
|
timer_.expires_after(std::chrono::seconds(15));
|
||||||
|
|
||||||
// Perform the SSL shutdown
|
// Perform the SSL shutdown
|
||||||
ws_.next_layer().async_shutdown(
|
ws_.next_layer().async_shutdown(
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&ssl_websocket_session::on_shutdown,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1)));
|
&ssl_websocket_session::on_shutdown,
|
||||||
|
shared_from_this(),
|
||||||
|
std::placeholders::_1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -630,10 +645,12 @@ class http_session
|
|||||||
http::async_write(
|
http::async_write(
|
||||||
self_.derived().stream(),
|
self_.derived().stream(),
|
||||||
msg_,
|
msg_,
|
||||||
self_.strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&http_session::on_write,
|
self_.strand_,
|
||||||
self_.derived().shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1)));
|
&http_session::on_write,
|
||||||
|
self_.derived().shared_from_this(),
|
||||||
|
std::placeholders::_1)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -652,20 +669,21 @@ class http_session
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
boost::asio::steady_timer timer_;
|
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_;
|
boost::beast::flat_buffer buffer_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Construct the session
|
// Construct the session
|
||||||
http_session(
|
http_session(
|
||||||
boost::asio::io_service& ios,
|
boost::asio::io_context& ioc,
|
||||||
boost::beast::flat_buffer buffer,
|
boost::beast::flat_buffer buffer,
|
||||||
std::string const& doc_root)
|
std::string const& doc_root)
|
||||||
: doc_root_(doc_root)
|
: doc_root_(doc_root)
|
||||||
, queue_(*this)
|
, queue_(*this)
|
||||||
, timer_(ios,
|
, timer_(ioc,
|
||||||
(std::chrono::steady_clock::time_point::max)())
|
(std::chrono::steady_clock::time_point::max)())
|
||||||
, strand_(ios)
|
, strand_(ioc.get_executor())
|
||||||
, buffer_(std::move(buffer))
|
, buffer_(std::move(buffer))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -674,17 +692,19 @@ public:
|
|||||||
do_read()
|
do_read()
|
||||||
{
|
{
|
||||||
// Set the timer
|
// Set the timer
|
||||||
timer_.expires_from_now(std::chrono::seconds(15));
|
timer_.expires_after(std::chrono::seconds(15));
|
||||||
|
|
||||||
// Read a request
|
// Read a request
|
||||||
http::async_read(
|
http::async_read(
|
||||||
derived().stream(),
|
derived().stream(),
|
||||||
buffer_,
|
buffer_,
|
||||||
req_,
|
req_,
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&http_session::on_read,
|
strand_,
|
||||||
derived().shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1)));
|
&http_session::on_read,
|
||||||
|
derived().shared_from_this(),
|
||||||
|
std::placeholders::_1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when the timer expires.
|
// Called when the timer expires.
|
||||||
@ -695,15 +715,17 @@ public:
|
|||||||
return fail(ec, "timer");
|
return fail(ec, "timer");
|
||||||
|
|
||||||
// Verify that the timer really expired since the deadline may have moved.
|
// 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();
|
return derived().do_timeout();
|
||||||
|
|
||||||
// Wait on the timer
|
// Wait on the timer
|
||||||
timer_.async_wait(
|
timer_.async_wait(
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&http_session::on_timer,
|
strand_,
|
||||||
derived().shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1)));
|
&http_session::on_timer,
|
||||||
|
derived().shared_from_this(),
|
||||||
|
std::placeholders::_1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -769,7 +791,8 @@ class plain_http_session
|
|||||||
, public std::enable_shared_from_this<plain_http_session>
|
, public std::enable_shared_from_this<plain_http_session>
|
||||||
{
|
{
|
||||||
tcp::socket socket_;
|
tcp::socket socket_;
|
||||||
boost::asio::io_service::strand strand_;
|
boost::asio::strand<
|
||||||
|
boost::asio::io_context::executor_type> strand_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Create the http_session
|
// Create the http_session
|
||||||
@ -778,11 +801,11 @@ public:
|
|||||||
boost::beast::flat_buffer buffer,
|
boost::beast::flat_buffer buffer,
|
||||||
std::string const& doc_root)
|
std::string const& doc_root)
|
||||||
: http_session<plain_http_session>(
|
: http_session<plain_http_session>(
|
||||||
socket.get_io_service(),
|
socket.get_executor().context(),
|
||||||
std::move(buffer),
|
std::move(buffer),
|
||||||
doc_root)
|
doc_root)
|
||||||
, socket_(std::move(socket))
|
, 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>
|
, public std::enable_shared_from_this<ssl_http_session>
|
||||||
{
|
{
|
||||||
ssl_stream<tcp::socket> stream_;
|
ssl_stream<tcp::socket> stream_;
|
||||||
boost::asio::io_service::strand strand_;
|
boost::asio::strand<
|
||||||
|
boost::asio::io_context::executor_type> strand_;
|
||||||
bool eof_ = false;
|
bool eof_ = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -849,11 +873,11 @@ public:
|
|||||||
boost::beast::flat_buffer buffer,
|
boost::beast::flat_buffer buffer,
|
||||||
std::string const& doc_root)
|
std::string const& doc_root)
|
||||||
: http_session<ssl_http_session>(
|
: http_session<ssl_http_session>(
|
||||||
socket.get_io_service(),
|
socket.get_executor().context(),
|
||||||
std::move(buffer),
|
std::move(buffer),
|
||||||
doc_root)
|
doc_root)
|
||||||
, stream_(std::move(socket), ctx)
|
, stream_(std::move(socket), ctx)
|
||||||
, strand_(stream_.get_io_service())
|
, strand_(stream_.get_executor())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -880,18 +904,20 @@ public:
|
|||||||
on_timer({});
|
on_timer({});
|
||||||
|
|
||||||
// Set the timer
|
// Set the timer
|
||||||
timer_.expires_from_now(std::chrono::seconds(15));
|
timer_.expires_after(std::chrono::seconds(15));
|
||||||
|
|
||||||
// Perform the SSL handshake
|
// Perform the SSL handshake
|
||||||
// Note, this is the buffered version of the handshake.
|
// Note, this is the buffered version of the handshake.
|
||||||
stream_.async_handshake(
|
stream_.async_handshake(
|
||||||
ssl::stream_base::server,
|
ssl::stream_base::server,
|
||||||
buffer_.data(),
|
buffer_.data(),
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&ssl_http_session::on_handshake,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&ssl_http_session::on_handshake,
|
||||||
std::placeholders::_2)));
|
shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2)));
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
on_handshake(
|
on_handshake(
|
||||||
@ -917,14 +943,16 @@ public:
|
|||||||
eof_ = true;
|
eof_ = true;
|
||||||
|
|
||||||
// Set the timer
|
// Set the timer
|
||||||
timer_.expires_from_now(std::chrono::seconds(15));
|
timer_.expires_after(std::chrono::seconds(15));
|
||||||
|
|
||||||
// Perform the SSL shutdown
|
// Perform the SSL shutdown
|
||||||
stream_.async_shutdown(
|
stream_.async_shutdown(
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&ssl_http_session::on_shutdown,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1)));
|
&ssl_http_session::on_shutdown,
|
||||||
|
shared_from_this(),
|
||||||
|
std::placeholders::_1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -962,7 +990,8 @@ class detect_session : public std::enable_shared_from_this<detect_session>
|
|||||||
{
|
{
|
||||||
tcp::socket socket_;
|
tcp::socket socket_;
|
||||||
ssl::context& ctx_;
|
ssl::context& ctx_;
|
||||||
boost::asio::io_service::strand strand_;
|
boost::asio::strand<
|
||||||
|
boost::asio::io_context::executor_type> strand_;
|
||||||
std::string const& doc_root_;
|
std::string const& doc_root_;
|
||||||
boost::beast::flat_buffer buffer_;
|
boost::beast::flat_buffer buffer_;
|
||||||
|
|
||||||
@ -974,7 +1003,7 @@ public:
|
|||||||
std::string const& doc_root)
|
std::string const& doc_root)
|
||||||
: socket_(std::move(socket))
|
: socket_(std::move(socket))
|
||||||
, ctx_(ctx)
|
, ctx_(ctx)
|
||||||
, strand_(socket_.get_io_service())
|
, strand_(socket_.get_executor())
|
||||||
, doc_root_(doc_root)
|
, doc_root_(doc_root)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -986,11 +1015,13 @@ public:
|
|||||||
async_detect_ssl(
|
async_detect_ssl(
|
||||||
socket_,
|
socket_,
|
||||||
buffer_,
|
buffer_,
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&detect_session::on_detect,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&detect_session::on_detect,
|
||||||
std::placeholders::_2)));
|
shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1029,13 +1060,13 @@ class listener : public std::enable_shared_from_this<listener>
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
listener(
|
listener(
|
||||||
boost::asio::io_service& ios,
|
boost::asio::io_context& ioc,
|
||||||
ssl::context& ctx,
|
ssl::context& ctx,
|
||||||
tcp::endpoint endpoint,
|
tcp::endpoint endpoint,
|
||||||
std::string const& doc_root)
|
std::string const& doc_root)
|
||||||
: ctx_(ctx)
|
: ctx_(ctx)
|
||||||
, acceptor_(ios)
|
, acceptor_(ioc)
|
||||||
, socket_(ios)
|
, socket_(ioc)
|
||||||
, doc_root_(doc_root)
|
, doc_root_(doc_root)
|
||||||
{
|
{
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
@ -1058,7 +1089,7 @@ public:
|
|||||||
|
|
||||||
// Start listening for connections
|
// Start listening for connections
|
||||||
acceptor_.listen(
|
acceptor_.listen(
|
||||||
boost::asio::socket_base::max_connections, ec);
|
boost::asio::socket_base::max_listen_connections, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
fail(ec, "listen");
|
fail(ec, "listen");
|
||||||
@ -1120,13 +1151,13 @@ int main(int argc, char* argv[])
|
|||||||
" advanced-server-flex 0.0.0.0 8080 . 1\n";
|
" advanced-server-flex 0.0.0.0 8080 . 1\n";
|
||||||
return EXIT_FAILURE;
|
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 port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||||
std::string const doc_root = argv[3];
|
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
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios{threads};
|
boost::asio::io_context ioc{threads};
|
||||||
|
|
||||||
// The SSL context is required, and holds certificates
|
// The SSL context is required, and holds certificates
|
||||||
ssl::context ctx{ssl::context::sslv23};
|
ssl::context ctx{ssl::context::sslv23};
|
||||||
@ -1136,7 +1167,7 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
// Create and launch a listening port
|
// Create and launch a listening port
|
||||||
std::make_shared<listener>(
|
std::make_shared<listener>(
|
||||||
ios,
|
ioc,
|
||||||
ctx,
|
ctx,
|
||||||
tcp::endpoint{address, port},
|
tcp::endpoint{address, port},
|
||||||
doc_root)->run();
|
doc_root)->run();
|
||||||
@ -1146,11 +1177,11 @@ int main(int argc, char* argv[])
|
|||||||
v.reserve(threads - 1);
|
v.reserve(threads - 1);
|
||||||
for(auto i = threads - 1; i > 0; --i)
|
for(auto i = threads - 1; i > 0; --i)
|
||||||
v.emplace_back(
|
v.emplace_back(
|
||||||
[&ios]
|
[&ioc]
|
||||||
{
|
{
|
||||||
ios.run();
|
ioc.run();
|
||||||
});
|
});
|
||||||
ios.run();
|
ioc.run();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <boost/beast/http.hpp>
|
#include <boost/beast/http.hpp>
|
||||||
#include <boost/beast/websocket.hpp>
|
#include <boost/beast/websocket.hpp>
|
||||||
#include <boost/beast/version.hpp>
|
#include <boost/beast/version.hpp>
|
||||||
|
#include <boost/asio/bind_executor.hpp>
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
#include <boost/asio/strand.hpp>
|
#include <boost/asio/strand.hpp>
|
||||||
#include <boost/asio/steady_timer.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>
|
class websocket_session : public std::enable_shared_from_this<websocket_session>
|
||||||
{
|
{
|
||||||
websocket::stream<tcp::socket> ws_;
|
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::asio::steady_timer timer_;
|
||||||
boost::beast::multi_buffer buffer_;
|
boost::beast::multi_buffer buffer_;
|
||||||
|
|
||||||
@ -223,8 +225,8 @@ public:
|
|||||||
explicit
|
explicit
|
||||||
websocket_session(tcp::socket socket)
|
websocket_session(tcp::socket socket)
|
||||||
: ws_(std::move(socket))
|
: ws_(std::move(socket))
|
||||||
, strand_(ws_.get_io_service())
|
, strand_(ws_.get_executor())
|
||||||
, timer_(ws_.get_io_service(),
|
, timer_(ws_.get_executor().context(),
|
||||||
(std::chrono::steady_clock::time_point::max)())
|
(std::chrono::steady_clock::time_point::max)())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -239,15 +241,17 @@ public:
|
|||||||
on_timer({});
|
on_timer({});
|
||||||
|
|
||||||
// Set the timer
|
// Set the timer
|
||||||
timer_.expires_from_now(std::chrono::seconds(15));
|
timer_.expires_after(std::chrono::seconds(15));
|
||||||
|
|
||||||
// Accept the websocket handshake
|
// Accept the websocket handshake
|
||||||
ws_.async_accept(
|
ws_.async_accept(
|
||||||
req,
|
req,
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&websocket_session::on_accept,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1)));
|
&websocket_session::on_accept,
|
||||||
|
shared_from_this(),
|
||||||
|
std::placeholders::_1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when the timer expires.
|
// Called when the timer expires.
|
||||||
@ -258,7 +262,7 @@ public:
|
|||||||
return fail(ec, "timer");
|
return fail(ec, "timer");
|
||||||
|
|
||||||
// Verify that the timer really expired since the deadline may have moved.
|
// 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
|
// Closing the socket cancels all outstanding operations. They
|
||||||
// will complete with boost::asio::error::operation_aborted
|
// will complete with boost::asio::error::operation_aborted
|
||||||
@ -269,10 +273,12 @@ public:
|
|||||||
|
|
||||||
// Wait on the timer
|
// Wait on the timer
|
||||||
timer_.async_wait(
|
timer_.async_wait(
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&websocket_session::on_timer,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1)));
|
&websocket_session::on_timer,
|
||||||
|
shared_from_this(),
|
||||||
|
std::placeholders::_1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -293,16 +299,18 @@ public:
|
|||||||
do_read()
|
do_read()
|
||||||
{
|
{
|
||||||
// Set the timer
|
// Set the timer
|
||||||
timer_.expires_from_now(std::chrono::seconds(15));
|
timer_.expires_after(std::chrono::seconds(15));
|
||||||
|
|
||||||
// Read a message into our buffer
|
// Read a message into our buffer
|
||||||
ws_.async_read(
|
ws_.async_read(
|
||||||
buffer_,
|
buffer_,
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&websocket_session::on_read,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&websocket_session::on_read,
|
||||||
std::placeholders::_2)));
|
shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -327,11 +335,13 @@ public:
|
|||||||
ws_.text(ws_.got_text());
|
ws_.text(ws_.got_text());
|
||||||
ws_.async_write(
|
ws_.async_write(
|
||||||
buffer_.data(),
|
buffer_.data(),
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&websocket_session::on_write,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&websocket_session::on_write,
|
||||||
std::placeholders::_2)));
|
shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -432,10 +442,12 @@ class http_session : public std::enable_shared_from_this<http_session>
|
|||||||
http::async_write(
|
http::async_write(
|
||||||
self_.socket_,
|
self_.socket_,
|
||||||
msg_,
|
msg_,
|
||||||
self_.strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&http_session::on_write,
|
self_.strand_,
|
||||||
self_.shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1)));
|
&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_;
|
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::asio::steady_timer timer_;
|
||||||
boost::beast::flat_buffer buffer_;
|
boost::beast::flat_buffer buffer_;
|
||||||
std::string const& doc_root_;
|
std::string const& doc_root_;
|
||||||
@ -463,8 +476,8 @@ public:
|
|||||||
tcp::socket socket,
|
tcp::socket socket,
|
||||||
std::string const& doc_root)
|
std::string const& doc_root)
|
||||||
: socket_(std::move(socket))
|
: socket_(std::move(socket))
|
||||||
, strand_(socket_.get_io_service())
|
, strand_(socket_.get_executor())
|
||||||
, timer_(socket_.get_io_service(),
|
, timer_(socket_.get_executor().context(),
|
||||||
(std::chrono::steady_clock::time_point::max)())
|
(std::chrono::steady_clock::time_point::max)())
|
||||||
, doc_root_(doc_root)
|
, doc_root_(doc_root)
|
||||||
, queue_(*this)
|
, queue_(*this)
|
||||||
@ -486,14 +499,16 @@ public:
|
|||||||
do_read()
|
do_read()
|
||||||
{
|
{
|
||||||
// Set the timer
|
// Set the timer
|
||||||
timer_.expires_from_now(std::chrono::seconds(15));
|
timer_.expires_after(std::chrono::seconds(15));
|
||||||
|
|
||||||
// Read a request
|
// Read a request
|
||||||
http::async_read(socket_, buffer_, req_,
|
http::async_read(socket_, buffer_, req_,
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&http_session::on_read,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1)));
|
&http_session::on_read,
|
||||||
|
shared_from_this(),
|
||||||
|
std::placeholders::_1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when the timer expires.
|
// Called when the timer expires.
|
||||||
@ -504,7 +519,7 @@ public:
|
|||||||
return fail(ec, "timer");
|
return fail(ec, "timer");
|
||||||
|
|
||||||
// Verify that the timer really expired since the deadline may have moved.
|
// 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
|
// Closing the socket cancels all outstanding operations. They
|
||||||
// will complete with boost::asio::error::operation_aborted
|
// will complete with boost::asio::error::operation_aborted
|
||||||
@ -515,10 +530,12 @@ public:
|
|||||||
|
|
||||||
// Wait on the timer
|
// Wait on the timer
|
||||||
timer_.async_wait(
|
timer_.async_wait(
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&http_session::on_timer,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1)));
|
&http_session::on_timer,
|
||||||
|
shared_from_this(),
|
||||||
|
std::placeholders::_1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -599,11 +616,11 @@ class listener : public std::enable_shared_from_this<listener>
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
listener(
|
listener(
|
||||||
boost::asio::io_service& ios,
|
boost::asio::io_context& ioc,
|
||||||
tcp::endpoint endpoint,
|
tcp::endpoint endpoint,
|
||||||
std::string const& doc_root)
|
std::string const& doc_root)
|
||||||
: acceptor_(ios)
|
: acceptor_(ioc)
|
||||||
, socket_(ios)
|
, socket_(ioc)
|
||||||
, doc_root_(doc_root)
|
, doc_root_(doc_root)
|
||||||
{
|
{
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
@ -626,7 +643,7 @@ public:
|
|||||||
|
|
||||||
// Start listening for connections
|
// Start listening for connections
|
||||||
acceptor_.listen(
|
acceptor_.listen(
|
||||||
boost::asio::socket_base::max_connections, ec);
|
boost::asio::socket_base::max_listen_connections, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
fail(ec, "listen");
|
fail(ec, "listen");
|
||||||
@ -687,17 +704,17 @@ int main(int argc, char* argv[])
|
|||||||
" advanced-server 0.0.0.0 8080 . 1\n";
|
" advanced-server 0.0.0.0 8080 . 1\n";
|
||||||
return EXIT_FAILURE;
|
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 port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||||
std::string const doc_root = argv[3];
|
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
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios{threads};
|
boost::asio::io_context ioc{threads};
|
||||||
|
|
||||||
// Create and launch a listening port
|
// Create and launch a listening port
|
||||||
std::make_shared<listener>(
|
std::make_shared<listener>(
|
||||||
ios,
|
ioc,
|
||||||
tcp::endpoint{address, port},
|
tcp::endpoint{address, port},
|
||||||
doc_root)->run();
|
doc_root)->run();
|
||||||
|
|
||||||
@ -706,11 +723,11 @@ int main(int argc, char* argv[])
|
|||||||
v.reserve(threads - 1);
|
v.reserve(threads - 1);
|
||||||
for(auto i = threads - 1; i > 0; --i)
|
for(auto i = threads - 1; i > 0; --i)
|
||||||
v.emplace_back(
|
v.emplace_back(
|
||||||
[&ios]
|
[&ioc]
|
||||||
{
|
{
|
||||||
ios.run();
|
ioc.run();
|
||||||
});
|
});
|
||||||
ios.run();
|
ioc.run();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,8 @@ is_ssl_handshake(
|
|||||||
ConstBufferSequence const& buffers)
|
ConstBufferSequence const& buffers)
|
||||||
{
|
{
|
||||||
// Make sure buffers meets the requirements
|
// 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");
|
"ConstBufferSequence requirements not met");
|
||||||
|
|
||||||
// We need at least one byte to really do anything
|
// We need at least one byte to really do anything
|
||||||
@ -135,7 +136,8 @@ detect_ssl(
|
|||||||
// Make sure arguments meet the requirements
|
// Make sure arguments meet the requirements
|
||||||
static_assert(beast::is_sync_read_stream<SyncReadStream>::value,
|
static_assert(beast::is_sync_read_stream<SyncReadStream>::value,
|
||||||
"SyncReadStream requirements not met");
|
"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");
|
"DynamicBuffer requirements not met");
|
||||||
|
|
||||||
// Loop until an error occurs or we get a definitive answer
|
// Loop until an error occurs or we get a definitive answer
|
||||||
@ -219,15 +221,15 @@ detect_ssl(
|
|||||||
Regardless of whether the asynchronous operation completes
|
Regardless of whether the asynchronous operation completes
|
||||||
immediately or not, the handler will not be invoked from within
|
immediately or not, the handler will not be invoked from within
|
||||||
this function. Invocation of the handler will be performed in a
|
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<
|
template<
|
||||||
class AsyncReadStream,
|
class AsyncReadStream,
|
||||||
class DynamicBuffer,
|
class DynamicBuffer,
|
||||||
class CompletionToken>
|
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,
|
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(
|
async_detect_ssl(
|
||||||
AsyncReadStream& stream,
|
AsyncReadStream& stream,
|
||||||
DynamicBuffer& buffer,
|
DynamicBuffer& buffer,
|
||||||
@ -249,9 +251,9 @@ template<
|
|||||||
class AsyncReadStream,
|
class AsyncReadStream,
|
||||||
class DynamicBuffer,
|
class DynamicBuffer,
|
||||||
class CompletionToken>
|
class CompletionToken>
|
||||||
boost::beast::async_return_type<
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
CompletionToken,
|
CompletionToken,
|
||||||
void(boost::beast::error_code, boost::tribool)>
|
void(boost::beast::error_code, boost::tribool))
|
||||||
async_detect_ssl(
|
async_detect_ssl(
|
||||||
AsyncReadStream& stream,
|
AsyncReadStream& stream,
|
||||||
DynamicBuffer& buffer,
|
DynamicBuffer& buffer,
|
||||||
@ -262,26 +264,29 @@ async_detect_ssl(
|
|||||||
// Make sure arguments meet the requirements
|
// Make sure arguments meet the requirements
|
||||||
static_assert(beast::is_async_read_stream<AsyncReadStream>::value,
|
static_assert(beast::is_async_read_stream<AsyncReadStream>::value,
|
||||||
"SyncReadStream requirements not met");
|
"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");
|
"DynamicBuffer requirements not met");
|
||||||
|
|
||||||
// This helper manages some of the handler's lifetime and
|
// This helper manages some of the handler's lifetime and
|
||||||
// uses the result and handler specializations associated with
|
// uses the result and handler specializations associated with
|
||||||
// the completion token to help customize the return value.
|
// 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};
|
CompletionToken, void(beast::error_code, boost::tribool)> init{token};
|
||||||
|
|
||||||
// Create the composed operation and launch it. This is a constructor
|
// 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,
|
// to convert the completion token into the correct handler type,
|
||||||
// allowing user defined specializations of the async result template
|
// allowing user defined specializations of the async result template
|
||||||
// to take effect.
|
// to take effect.
|
||||||
//
|
//
|
||||||
detect_ssl_op<AsyncReadStream, DynamicBuffer, beast::handler_type<
|
detect_ssl_op<
|
||||||
CompletionToken, void(beast::error_code, boost::tribool)>>{
|
AsyncReadStream,
|
||||||
stream, buffer, init.completion_handler}(
|
DynamicBuffer,
|
||||||
beast::error_code{}, 0);
|
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.
|
// This hook lets the caller see a return value when appropriate.
|
||||||
// For example this might return std::future<error_code, boost::tribool> if
|
// 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
|
// Determines if the next asynchronous operation represents a
|
||||||
// continuation of the asynchronous flow of control associated
|
// continuation of the asynchronous flow of control associated
|
||||||
// with the final handler. If we are past step two, it means
|
// 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_));
|
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
|
// Our main entry point. This will get called as our
|
||||||
// intermediate operations complete. Definition below.
|
// 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
|
// We need to invoke the handler, but the guarantee
|
||||||
// is that the handler will not be called before the
|
// is that the handler will not be called before the
|
||||||
// call to async_detect_ssl returns, so we must post
|
// 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
|
// `bind_handler` lets us bind arguments in a safe way
|
||||||
// that preserves the type customization hooks of the
|
// that preserves the type customization hooks of the
|
||||||
// original handler.
|
// original handler.
|
||||||
step_ = 1;
|
step_ = 1;
|
||||||
return stream_.get_io_service().post(
|
return boost::asio::post(
|
||||||
|
stream_.get_executor(),
|
||||||
beast::bind_handler(std::move(*this), ec, 0));
|
beast::bind_handler(std::move(*this), ec, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,21 +10,21 @@
|
|||||||
#ifndef BOOST_BEAST_EXAMPLE_COMMON_SESSION_ALLOC_HPP
|
#ifndef BOOST_BEAST_EXAMPLE_COMMON_SESSION_ALLOC_HPP
|
||||||
#define 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_continuation_hook.hpp>
|
||||||
#include <boost/asio/handler_invoke_hook.hpp>
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/intrusive/list.hpp>
|
#include <boost/intrusive/list.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
template<class Context>
|
template<class Context>
|
||||||
class session_alloc_base
|
class session_alloc_base
|
||||||
{
|
{
|
||||||
template<class Handler>
|
protected:
|
||||||
class wrapped_handler;
|
|
||||||
|
|
||||||
class pool_t
|
class pool_t
|
||||||
{
|
{
|
||||||
using hook_type =
|
using hook_type =
|
||||||
@ -78,23 +78,18 @@ class session_alloc_base
|
|||||||
boost::intrusive::constant_time_size<
|
boost::intrusive::constant_time_size<
|
||||||
true>>::type;
|
true>>::type;
|
||||||
|
|
||||||
Context* ctx_;
|
|
||||||
std::size_t refs_ = 1; // shared count
|
std::size_t refs_ = 1; // shared count
|
||||||
std::size_t high_ = 0; // highest used
|
std::size_t high_ = 0; // highest used
|
||||||
std::size_t size_ = 0; // size of buf_
|
std::size_t size_ = 0; // size of buf_
|
||||||
char* buf_ = nullptr; // a large block
|
char* buf_ = nullptr; // a large block
|
||||||
list_type list_; // list of allocations
|
list_type list_; // list of allocations
|
||||||
|
|
||||||
explicit
|
pool_t() = default;
|
||||||
pool_t(Context* ctx)
|
|
||||||
: ctx_(ctx)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static
|
static
|
||||||
pool_t&
|
pool_t&
|
||||||
construct(Context* ctx);
|
construct();
|
||||||
|
|
||||||
~pool_t();
|
~pool_t();
|
||||||
|
|
||||||
@ -110,73 +105,178 @@ class session_alloc_base
|
|||||||
void
|
void
|
||||||
dealloc(void* pv, std::size_t n);
|
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>
|
template<class T>
|
||||||
class session_alloc : public session_alloc_base<Context>
|
class session_alloc
|
||||||
|
: private detail::session_alloc_base<void>
|
||||||
{
|
{
|
||||||
template<class U, class C>
|
template<class U>
|
||||||
friend class session_alloc;
|
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:
|
public:
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
using is_always_equal = std::false_type;
|
using is_always_equal = std::false_type;
|
||||||
@ -193,21 +293,32 @@ public:
|
|||||||
using other = session_alloc<U>;
|
using other = session_alloc<U>;
|
||||||
};
|
};
|
||||||
|
|
||||||
session_alloc() = default;
|
session_alloc& operator=(session_alloc const&) = delete;
|
||||||
session_alloc(session_alloc const&) = default;
|
|
||||||
|
~session_alloc()
|
||||||
|
{
|
||||||
|
pool_.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
session_alloc()
|
||||||
|
: pool_(pool_t::construct())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
session_alloc(session_alloc const& other) noexcept
|
||||||
|
: pool_(other.pool_.addref())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
template<class U>
|
template<class U>
|
||||||
session_alloc(session_alloc<U> const& other)
|
session_alloc(session_alloc<U> const& other) noexcept
|
||||||
: session_alloc_base<Context>(static_cast<
|
: pool_(other.pool_)
|
||||||
session_alloc_base<Context> const&>(other))
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit
|
template<class Handler>
|
||||||
session_alloc(Context& ctx)
|
wrapped_handler<typename std::decay<Handler>::type>
|
||||||
: session_alloc_base<Context>(ctx)
|
wrap(Handler&& handler);
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
value_type*
|
value_type*
|
||||||
allocate(size_type n)
|
allocate(size_type n)
|
||||||
@ -257,209 +368,67 @@ public:
|
|||||||
{
|
{
|
||||||
return ! (lhs == rhs);
|
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>
|
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_;
|
return alloc_;
|
||||||
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_));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class Context>
|
template<class T>
|
||||||
|
template<class Handler>
|
||||||
auto
|
auto
|
||||||
session_alloc_base<Context>::
|
session_alloc<T>::
|
||||||
pool_t::
|
wrap(Handler&& handler) ->
|
||||||
construct(Context* ctx) ->
|
wrapped_handler<typename std::decay<Handler>::type>
|
||||||
pool_t&
|
|
||||||
{
|
{
|
||||||
using boost::asio::asio_handler_allocate;
|
return wrapped_handler<
|
||||||
return *new(asio_handler_allocate(
|
typename std::decay<Handler>::type>(
|
||||||
sizeof(pool_t), ctx)) pool_t{ctx};
|
std::forward<Handler>(handler), *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Context>
|
namespace boost {
|
||||||
session_alloc_base<Context>::
|
namespace asio {
|
||||||
pool_t::
|
template<class T, class Handler, class Executor>
|
||||||
~pool_t()
|
struct associated_executor<
|
||||||
|
session_alloc<T>::wrapped_handler<Handler>, Executor>
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(list_.size() == 0);
|
using type = typename
|
||||||
if(buf_)
|
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;
|
return associated_executor<
|
||||||
asio_handler_deallocate(buf_, size_, ctx_);
|
Handler, Executor>::get(h.h_, ex);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
} // asio
|
||||||
template<class Context>
|
} // boost
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -52,9 +52,6 @@ public:
|
|||||||
/// Structure for use with deprecated impl_type.
|
/// Structure for use with deprecated impl_type.
|
||||||
using impl_struct = typename stream_type::impl_struct;
|
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.
|
/// The type of the next layer.
|
||||||
using next_layer_type = typename stream_type::next_layer_type;
|
using next_layer_type = typename stream_type::next_layer_type;
|
||||||
|
|
||||||
@ -64,14 +61,16 @@ public:
|
|||||||
ssl_stream(
|
ssl_stream(
|
||||||
boost::asio::ip::tcp::socket socket,
|
boost::asio::ip::tcp::socket socket,
|
||||||
boost::asio::ssl::context& ctx)
|
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)
|
, ctx_(&ctx)
|
||||||
{
|
{
|
||||||
p_->next_layer() = std::move(socket);
|
p_->next_layer() = std::move(socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_stream(ssl_stream&& other)
|
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_)
|
, ctx_(other.ctx_)
|
||||||
{
|
{
|
||||||
using std::swap;
|
using std::swap;
|
||||||
@ -80,8 +79,8 @@ public:
|
|||||||
|
|
||||||
ssl_stream& operator=(ssl_stream&& other)
|
ssl_stream& operator=(ssl_stream&& other)
|
||||||
{
|
{
|
||||||
std::unique_ptr<stream_type> p(
|
std::unique_ptr<stream_type> p(new stream_type{
|
||||||
new stream_type{other.get_io_service(), other.ctx_});
|
other.get_executor().context(), other.ctx_});
|
||||||
using std::swap;
|
using std::swap;
|
||||||
swap(p_, p);
|
swap(p_, p);
|
||||||
swap(p_, other.p_);
|
swap(p_, other.p_);
|
||||||
@ -89,10 +88,10 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::asio::io_service&
|
decltype(p_->get_executor())
|
||||||
get_io_service()
|
get_executor() noexcept
|
||||||
{
|
{
|
||||||
return p_->get_io_service();
|
return p_->get_executor();
|
||||||
}
|
}
|
||||||
|
|
||||||
native_handle_type
|
native_handle_type
|
||||||
@ -101,12 +100,6 @@ public:
|
|||||||
return p_->native_handle();
|
return p_->native_handle();
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_type
|
|
||||||
impl()
|
|
||||||
{
|
|
||||||
return p_->impl();
|
|
||||||
}
|
|
||||||
|
|
||||||
next_layer_type const&
|
next_layer_type const&
|
||||||
next_layer() 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,
|
static_assert(is_sync_stream<SyncStream>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
|
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(
|
||||||
|
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
|
|
||||||
// Insert or replace the Expect field
|
// Insert or replace the Expect field
|
||||||
@ -123,7 +124,8 @@ receive_expect_100_continue(
|
|||||||
static_assert(is_sync_stream<SyncStream>::value,
|
static_assert(is_sync_stream<SyncStream>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
|
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(
|
||||||
|
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
|
|
||||||
// Declare a parser for a request with a string body
|
// 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,
|
static_assert(is_sync_write_stream<SyncWriteStream>::value,
|
||||||
"SyncWriteStream requirements not met");
|
"SyncWriteStream requirements not met");
|
||||||
|
|
||||||
using boost::asio::buffer_cast;
|
|
||||||
using boost::asio::buffer_size;
|
|
||||||
|
|
||||||
// Set up the response. We use the buffer_body type,
|
// Set up the response. We use the buffer_body type,
|
||||||
// allowing serialization to use manually provided buffers.
|
// allowing serialization to use manually provided buffers.
|
||||||
response<buffer_body> res;
|
response<buffer_body> res;
|
||||||
@ -293,7 +292,8 @@ void do_server_head(
|
|||||||
{
|
{
|
||||||
static_assert(is_sync_stream<SyncStream>::value,
|
static_assert(is_sync_stream<SyncStream>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(
|
||||||
|
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirments not met");
|
"DynamicBuffer requirments not met");
|
||||||
|
|
||||||
// We deliver this payload for all GET requests
|
// We deliver this payload for all GET requests
|
||||||
@ -386,7 +386,8 @@ do_head_request(
|
|||||||
// Do some type checking to be a good citizen
|
// Do some type checking to be a good citizen
|
||||||
static_assert(is_sync_stream<SyncStream>::value,
|
static_assert(is_sync_stream<SyncStream>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(
|
||||||
|
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirments not met");
|
"DynamicBuffer requirments not met");
|
||||||
|
|
||||||
// The interfaces we are using are low level and do not
|
// The interfaces we are using are low level and do not
|
||||||
@ -589,10 +590,6 @@ public:
|
|||||||
void
|
void
|
||||||
operator()(error_code& ec, ConstBufferSequence const& buffers) const
|
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
|
// Error codes must be cleared on success
|
||||||
ec = {};
|
ec = {};
|
||||||
|
|
||||||
@ -600,15 +597,16 @@ public:
|
|||||||
std::size_t bytes_transferred = 0;
|
std::size_t bytes_transferred = 0;
|
||||||
|
|
||||||
// Loop over the buffer sequence
|
// 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
|
// This is the next buffer in the sequence
|
||||||
boost::asio::const_buffer const buffer = *it;
|
boost::asio::const_buffer const buffer = *it;
|
||||||
|
|
||||||
// Write it to the std::ostream
|
// Write it to the std::ostream
|
||||||
os_.write(
|
os_.write(
|
||||||
buffer_cast<char const*>(buffer),
|
reinterpret_cast<char const*>(buffer.data()),
|
||||||
buffer_size(buffer));
|
buffer.size());
|
||||||
|
|
||||||
// If the std::ostream fails, convert it to an error code
|
// If the std::ostream fails, convert it to an error code
|
||||||
if(os_.fail())
|
if(os_.fail())
|
||||||
@ -714,13 +712,12 @@ read_istream(
|
|||||||
if(is.rdbuf()->in_avail() > 0)
|
if(is.rdbuf()->in_avail() > 0)
|
||||||
{
|
{
|
||||||
// Get a mutable buffer sequence for writing
|
// 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()));
|
static_cast<std::size_t>(is.rdbuf()->in_avail()));
|
||||||
|
|
||||||
// Now get everything we can from the istream
|
// Now get everything we can from the istream
|
||||||
buffer.commit(static_cast<std::size_t>(is.readsome(
|
buffer.commit(static_cast<std::size_t>(is.readsome(
|
||||||
boost::asio::buffer_cast<char*>(mb),
|
reinterpret_cast<char*>(b.data()), b.size())));
|
||||||
boost::asio::buffer_size(mb))));
|
|
||||||
}
|
}
|
||||||
else if(buffer.size() == 0)
|
else if(buffer.size() == 0)
|
||||||
{
|
{
|
||||||
@ -729,12 +726,10 @@ read_istream(
|
|||||||
if(! is.eof())
|
if(! is.eof())
|
||||||
{
|
{
|
||||||
// Get a mutable buffer sequence for writing
|
// 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.
|
// Try to get more from the istream. This might block.
|
||||||
is.read(
|
is.read(reinterpret_cast<char*>(b.data()), b.size());
|
||||||
boost::asio::buffer_cast<char*>(mb),
|
|
||||||
boost::asio::buffer_size(mb));
|
|
||||||
|
|
||||||
// If an error occurs on the istream then return it to the caller.
|
// If an error occurs on the istream then return it to the caller.
|
||||||
if(is.fail() && ! is.eof())
|
if(is.fail() && ! is.eof())
|
||||||
|
@ -23,7 +23,7 @@ auto
|
|||||||
async_echo(AsyncStream& stream, CompletionToken&& token)
|
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
|
//[example_core_echo_op_2
|
||||||
|
|
||||||
@ -61,14 +61,14 @@ async_echo(AsyncStream& stream, CompletionToken&& token)
|
|||||||
Regardless of whether the asynchronous operation completes
|
Regardless of whether the asynchronous operation completes
|
||||||
immediately or not, the handler will not be invoked from within
|
immediately or not, the handler will not be invoked from within
|
||||||
this function. Invocation of the handler will be performed in a
|
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<
|
template<
|
||||||
class AsyncStream,
|
class AsyncStream,
|
||||||
class CompletionToken>
|
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,
|
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(
|
async_echo(
|
||||||
AsyncStream& stream,
|
AsyncStream& stream,
|
||||||
CompletionToken&& token);
|
CompletionToken&& token);
|
||||||
@ -95,11 +95,13 @@ class echo_op
|
|||||||
// The buffer used to hold the input and output data.
|
// The buffer used to hold the input and output data.
|
||||||
//
|
//
|
||||||
// We use a custom allocator for performance, this allows
|
// 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
|
// re-use of memory allocated by composed operations during
|
||||||
// a continuation.
|
// 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
|
// handler_ptr requires that the first parameter to the
|
||||||
// contained object constructor is a reference to the
|
// contained object constructor is a reference to the
|
||||||
@ -108,7 +110,7 @@ class echo_op
|
|||||||
explicit state(Handler& handler, AsyncStream& stream_)
|
explicit state(Handler& handler, AsyncStream& stream_)
|
||||||
: stream(stream_)
|
: stream(stream_)
|
||||||
, buffer((std::numeric_limits<std::size_t>::max)(),
|
, 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
|
// The operation's data is kept in a cheap-to-copy smart
|
||||||
// pointer container called `handler_ptr`. This efficiently
|
// pointer container called `handler_ptr`. This efficiently
|
||||||
// satisfies the CopyConstructible requirements of completion
|
// satisfies the CopyConstructible requirements of completion
|
||||||
// handlers.
|
// handlers with expensive-to-copy state.
|
||||||
//
|
//
|
||||||
// `handler_ptr` uses these memory allocation hooks associated
|
// `handler_ptr` uses the allocator associated with the final
|
||||||
// with the final completion handler, in order to allocate the
|
// completion handler, in order to allocate the storage for `state`.
|
||||||
// storage for `state`:
|
|
||||||
//
|
|
||||||
// asio_handler_allocate
|
|
||||||
// asio_handler_deallocate
|
|
||||||
//
|
//
|
||||||
boost::beast::handler_ptr<state, Handler> p_;
|
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
|
// The entry point for this handler. This will get called
|
||||||
// as our intermediate operations complete. Definition below.
|
// as our intermediate operations complete. Definition below.
|
||||||
//
|
//
|
||||||
void operator()(boost::beast::error_code ec, std::size_t bytes_transferred);
|
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
|
//[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
|
// Determines if the next asynchronous operation represents a
|
||||||
// continuation of the asynchronous flow of control associated
|
// continuation of the asynchronous flow of control associated
|
||||||
// with the final handler. If we are past step one, it means
|
// 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
|
// Read a line and echo it back
|
||||||
//
|
//
|
||||||
template<class AsyncStream, class CompletionToken>
|
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)
|
async_echo(AsyncStream& stream, CompletionToken&& token)
|
||||||
{
|
{
|
||||||
// Make sure stream meets the requirements. We use static_assert
|
// 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
|
// uses the result and handler specializations associated with
|
||||||
// the completion token to help customize the return value.
|
// 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
|
// 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,
|
// to convert the completion token into the correct handler type,
|
||||||
// allowing user-defined specializations of the async_result template
|
// allowing user-defined specializations of the async_result template
|
||||||
// to be used.
|
// to be used.
|
||||||
//
|
//
|
||||||
echo_op<AsyncStream, boost::beast::handler_type<CompletionToken, void(boost::beast::error_code)>>{
|
echo_op<
|
||||||
stream, init.completion_handler}(boost::beast::error_code{}, 0);
|
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.
|
// This hook lets the caller see a return value when appropriate.
|
||||||
// For example this might return std::future<error_code> if
|
// 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)
|
int main(int, char** argv)
|
||||||
{
|
{
|
||||||
using address_type = boost::asio::ip::address;
|
|
||||||
using socket_type = boost::asio::ip::tcp::socket;
|
using socket_type = boost::asio::ip::tcp::socket;
|
||||||
using endpoint_type = boost::asio::ip::tcp::endpoint;
|
using endpoint_type = boost::asio::ip::tcp::endpoint;
|
||||||
|
|
||||||
// Create a listening socket, accept a connection, perform
|
// Create a listening socket, accept a connection, perform
|
||||||
// the echo, and then shut everything down and exit.
|
// the echo, and then shut everything down and exit.
|
||||||
boost::asio::io_service ios;
|
boost::asio::io_context ioc;
|
||||||
socket_type sock{ios};
|
socket_type sock{ioc};
|
||||||
boost::asio::ip::tcp::acceptor acceptor{ios};
|
boost::asio::ip::tcp::acceptor acceptor{ioc};
|
||||||
endpoint_type ep{address_type::from_string("0.0.0.0"), 0};
|
endpoint_type ep{boost::asio::ip::make_address("0.0.0.0"), 0};
|
||||||
acceptor.open(ep.protocol());
|
acceptor.open(ep.protocol());
|
||||||
acceptor.bind(ep);
|
acceptor.bind(ep);
|
||||||
acceptor.listen();
|
acceptor.listen();
|
||||||
@ -353,6 +331,6 @@ int main(int, char** argv)
|
|||||||
if(ec)
|
if(ec)
|
||||||
std::cerr << argv[0] << ": " << ec.message() << std::endl;
|
std::cerr << argv[0] << ": " << ec.message() << std::endl;
|
||||||
});
|
});
|
||||||
ios.run();
|
ioc.run();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -50,11 +50,11 @@ class session : public std::enable_shared_from_this<session>
|
|||||||
http::response<http::string_body> res_;
|
http::response<http::string_body> res_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Resolver and stream require an io_service
|
// Resolver and stream require an io_context
|
||||||
explicit
|
explicit
|
||||||
session(boost::asio::io_service& ios, ssl::context& ctx)
|
session(boost::asio::io_context& ioc, ssl::context& ctx)
|
||||||
: resolver_(ios)
|
: resolver_(ioc)
|
||||||
, stream_(ios, ctx)
|
, stream_(ioc, ctx)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +73,9 @@ public:
|
|||||||
req_.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
|
req_.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
|
||||||
|
|
||||||
// Look up the domain name
|
// Look up the domain name
|
||||||
resolver_.async_resolve({host, port},
|
resolver_.async_resolve(
|
||||||
|
host,
|
||||||
|
port,
|
||||||
std::bind(
|
std::bind(
|
||||||
&session::on_resolve,
|
&session::on_resolve,
|
||||||
shared_from_this(),
|
shared_from_this(),
|
||||||
@ -84,7 +86,7 @@ public:
|
|||||||
void
|
void
|
||||||
on_resolve(
|
on_resolve(
|
||||||
boost::system::error_code ec,
|
boost::system::error_code ec,
|
||||||
tcp::resolver::iterator result)
|
tcp::resolver::results_type results)
|
||||||
{
|
{
|
||||||
if(ec)
|
if(ec)
|
||||||
return fail(ec, "resolve");
|
return fail(ec, "resolve");
|
||||||
@ -92,7 +94,8 @@ public:
|
|||||||
// Make the connection on the IP address we get from a lookup
|
// Make the connection on the IP address we get from a lookup
|
||||||
boost::asio::async_connect(
|
boost::asio::async_connect(
|
||||||
stream_.next_layer(),
|
stream_.next_layer(),
|
||||||
result,
|
results.begin(),
|
||||||
|
results.end(),
|
||||||
std::bind(
|
std::bind(
|
||||||
&session::on_connect,
|
&session::on_connect,
|
||||||
shared_from_this(),
|
shared_from_this(),
|
||||||
@ -202,8 +205,8 @@ int main(int argc, char** argv)
|
|||||||
auto const port = argv[2];
|
auto const port = argv[2];
|
||||||
auto const target = argv[3];
|
auto const target = argv[3];
|
||||||
|
|
||||||
// The io_service is required for all I/O
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios;
|
boost::asio::io_context ioc;
|
||||||
|
|
||||||
// The SSL context is required, and holds certificates
|
// The SSL context is required, and holds certificates
|
||||||
ssl::context ctx{ssl::context::sslv23_client};
|
ssl::context ctx{ssl::context::sslv23_client};
|
||||||
@ -212,11 +215,11 @@ int main(int argc, char** argv)
|
|||||||
load_root_certificates(ctx);
|
load_root_certificates(ctx);
|
||||||
|
|
||||||
// Launch the asynchronous operation
|
// 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
|
// Run the I/O service. The call will return when
|
||||||
// the get operation is complete.
|
// the get operation is complete.
|
||||||
ios.run();
|
ioc.run();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -46,11 +46,11 @@ class session : public std::enable_shared_from_this<session>
|
|||||||
http::response<http::string_body> res_;
|
http::response<http::string_body> res_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Resolver and socket require an io_service
|
// Resolver and socket require an io_context
|
||||||
explicit
|
explicit
|
||||||
session(boost::asio::io_service& ios)
|
session(boost::asio::io_context& ioc)
|
||||||
: resolver_(ios)
|
: resolver_(ioc)
|
||||||
, socket_(ios)
|
, socket_(ioc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +69,9 @@ public:
|
|||||||
req_.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
|
req_.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
|
||||||
|
|
||||||
// Look up the domain name
|
// Look up the domain name
|
||||||
resolver_.async_resolve({host, port},
|
resolver_.async_resolve(
|
||||||
|
host,
|
||||||
|
port,
|
||||||
std::bind(
|
std::bind(
|
||||||
&session::on_resolve,
|
&session::on_resolve,
|
||||||
shared_from_this(),
|
shared_from_this(),
|
||||||
@ -80,13 +82,16 @@ public:
|
|||||||
void
|
void
|
||||||
on_resolve(
|
on_resolve(
|
||||||
boost::system::error_code ec,
|
boost::system::error_code ec,
|
||||||
tcp::resolver::iterator result)
|
tcp::resolver::results_type results)
|
||||||
{
|
{
|
||||||
if(ec)
|
if(ec)
|
||||||
return fail(ec, "resolve");
|
return fail(ec, "resolve");
|
||||||
|
|
||||||
// Make the connection on the IP address we get from a lookup
|
// 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(
|
std::bind(
|
||||||
&session::on_connect,
|
&session::on_connect,
|
||||||
shared_from_this(),
|
shared_from_this(),
|
||||||
@ -168,15 +173,15 @@ int main(int argc, char** argv)
|
|||||||
auto const port = argv[2];
|
auto const port = argv[2];
|
||||||
auto const target = argv[3];
|
auto const target = argv[3];
|
||||||
|
|
||||||
// The io_service is required for all I/O
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios;
|
boost::asio::io_context ioc;
|
||||||
|
|
||||||
// Launch the asynchronous operation
|
// 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
|
// Run the I/O service. The call will return when
|
||||||
// the get operation is complete.
|
// the get operation is complete.
|
||||||
ios.run();
|
ioc.run();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -46,23 +46,23 @@ do_session(
|
|||||||
std::string const& host,
|
std::string const& host,
|
||||||
std::string const& port,
|
std::string const& port,
|
||||||
std::string const& target,
|
std::string const& target,
|
||||||
boost::asio::io_service& ios,
|
boost::asio::io_context& ioc,
|
||||||
ssl::context& ctx,
|
ssl::context& ctx,
|
||||||
boost::asio::yield_context yield)
|
boost::asio::yield_context yield)
|
||||||
{
|
{
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
|
|
||||||
// These objects perform our I/O
|
// These objects perform our I/O
|
||||||
tcp::resolver resolver{ios};
|
tcp::resolver resolver{ioc};
|
||||||
ssl::stream<tcp::socket> stream{ios, ctx};
|
ssl::stream<tcp::socket> stream{ioc, ctx};
|
||||||
|
|
||||||
// Look up the domain name
|
// 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)
|
if(ec)
|
||||||
return fail(ec, "resolve");
|
return fail(ec, "resolve");
|
||||||
|
|
||||||
// Make the connection on the IP address we get from a lookup
|
// 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)
|
if(ec)
|
||||||
return fail(ec, "connect");
|
return fail(ec, "connect");
|
||||||
|
|
||||||
@ -126,8 +126,8 @@ int main(int argc, char** argv)
|
|||||||
auto const port = argv[2];
|
auto const port = argv[2];
|
||||||
auto const target = argv[3];
|
auto const target = argv[3];
|
||||||
|
|
||||||
// The io_service is required for all I/O
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios;
|
boost::asio::io_context ioc;
|
||||||
|
|
||||||
// The SSL context is required, and holds certificates
|
// The SSL context is required, and holds certificates
|
||||||
ssl::context ctx{ssl::context::sslv23_client};
|
ssl::context ctx{ssl::context::sslv23_client};
|
||||||
@ -136,18 +136,18 @@ int main(int argc, char** argv)
|
|||||||
load_root_certificates(ctx);
|
load_root_certificates(ctx);
|
||||||
|
|
||||||
// Launch the asynchronous operation
|
// Launch the asynchronous operation
|
||||||
boost::asio::spawn(ios, std::bind(
|
boost::asio::spawn(ioc, std::bind(
|
||||||
&do_session,
|
&do_session,
|
||||||
std::string(host),
|
std::string(host),
|
||||||
std::string(port),
|
std::string(port),
|
||||||
std::string(target),
|
std::string(target),
|
||||||
std::ref(ios),
|
std::ref(ioc),
|
||||||
std::ref(ctx),
|
std::ref(ctx),
|
||||||
std::placeholders::_1));
|
std::placeholders::_1));
|
||||||
|
|
||||||
// Run the I/O service. The call will return when
|
// Run the I/O service. The call will return when
|
||||||
// the get operation is complete.
|
// the get operation is complete.
|
||||||
ios.run();
|
ioc.run();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -42,22 +42,22 @@ do_session(
|
|||||||
std::string const& host,
|
std::string const& host,
|
||||||
std::string const& port,
|
std::string const& port,
|
||||||
std::string const& target,
|
std::string const& target,
|
||||||
boost::asio::io_service& ios,
|
boost::asio::io_context& ioc,
|
||||||
boost::asio::yield_context yield)
|
boost::asio::yield_context yield)
|
||||||
{
|
{
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
|
|
||||||
// These objects perform our I/O
|
// These objects perform our I/O
|
||||||
tcp::resolver resolver{ios};
|
tcp::resolver resolver{ioc};
|
||||||
tcp::socket socket{ios};
|
tcp::socket socket{ioc};
|
||||||
|
|
||||||
// Look up the domain name
|
// 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)
|
if(ec)
|
||||||
return fail(ec, "resolve");
|
return fail(ec, "resolve");
|
||||||
|
|
||||||
// Make the connection on the IP address we get from a lookup
|
// 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)
|
if(ec)
|
||||||
return fail(ec, "connect");
|
return fail(ec, "connect");
|
||||||
|
|
||||||
@ -114,21 +114,21 @@ int main(int argc, char** argv)
|
|||||||
auto const port = argv[2];
|
auto const port = argv[2];
|
||||||
auto const target = argv[3];
|
auto const target = argv[3];
|
||||||
|
|
||||||
// The io_service is required for all I/O
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios;
|
boost::asio::io_context ioc;
|
||||||
|
|
||||||
// Launch the asynchronous operation
|
// Launch the asynchronous operation
|
||||||
boost::asio::spawn(ios, std::bind(
|
boost::asio::spawn(ioc, std::bind(
|
||||||
&do_session,
|
&do_session,
|
||||||
std::string(host),
|
std::string(host),
|
||||||
std::string(port),
|
std::string(port),
|
||||||
std::string(target),
|
std::string(target),
|
||||||
std::ref(ios),
|
std::ref(ioc),
|
||||||
std::placeholders::_1));
|
std::placeholders::_1));
|
||||||
|
|
||||||
// Run the I/O service. The call will return when
|
// Run the I/O service. The call will return when
|
||||||
// the get operation is complete.
|
// the get operation is complete.
|
||||||
ios.run();
|
ioc.run();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,11 @@
|
|||||||
#include <boost/beast/core.hpp>
|
#include <boost/beast/core.hpp>
|
||||||
#include <boost/beast/http.hpp>
|
#include <boost/beast/http.hpp>
|
||||||
#include <boost/beast/version.hpp>
|
#include <boost/beast/version.hpp>
|
||||||
|
#include <boost/asio/bind_executor.hpp>
|
||||||
#include <boost/asio/connect.hpp>
|
#include <boost/asio/connect.hpp>
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
|
#include <boost/asio/post.hpp>
|
||||||
#include <boost/asio/strand.hpp>
|
#include <boost/asio/strand.hpp>
|
||||||
#include <boost/optional.hpp>
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
@ -43,16 +44,17 @@ namespace chrono = std::chrono; // from <chrono>
|
|||||||
// This structure aggregates statistics on all the sites
|
// This structure aggregates statistics on all the sites
|
||||||
class crawl_report
|
class crawl_report
|
||||||
{
|
{
|
||||||
boost::asio::io_service& ios_;
|
boost::asio::io_context& ioc_;
|
||||||
boost::asio::io_service::strand strand_;
|
boost::asio::strand<
|
||||||
|
boost::asio::io_context::executor_type> strand_;
|
||||||
std::atomic<std::size_t> index_;
|
std::atomic<std::size_t> index_;
|
||||||
std::vector<char const*> const& hosts_;
|
std::vector<char const*> const& hosts_;
|
||||||
std::size_t count_ = 0;
|
std::size_t count_ = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
crawl_report(boost::asio::io_service& ios)
|
crawl_report(boost::asio::io_context& ioc)
|
||||||
: ios_(ios)
|
: ioc_(ioc)
|
||||||
, strand_(ios_)
|
, strand_(ioc_.get_executor())
|
||||||
, index_(0)
|
, index_(0)
|
||||||
, hosts_(urls_large_data())
|
, hosts_(urls_large_data())
|
||||||
{
|
{
|
||||||
@ -64,18 +66,19 @@ public:
|
|||||||
void
|
void
|
||||||
aggregate(F const& f)
|
aggregate(F const& f)
|
||||||
{
|
{
|
||||||
ios_.post(strand_.wrap(
|
boost::asio::post(
|
||||||
[&, f]
|
strand_,
|
||||||
{
|
[&, f]
|
||||||
f(*this);
|
|
||||||
if(count_ % 100 == 0)
|
|
||||||
{
|
{
|
||||||
std::cerr <<
|
f(*this);
|
||||||
"Progress: " << count_ << " of " << hosts_.size() << "\n";
|
if(count_ % 100 == 0)
|
||||||
//std::cerr << *this;
|
{
|
||||||
}
|
std::cerr <<
|
||||||
++count_;
|
"Progress: " << count_ << " of " << hosts_.size() << "\n";
|
||||||
}));
|
//std::cerr << *this;
|
||||||
|
}
|
||||||
|
++count_;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the next host to check
|
// Returns the next host to check
|
||||||
@ -148,7 +151,8 @@ class worker : public std::enable_shared_from_this<worker>
|
|||||||
tcp::resolver resolver_;
|
tcp::resolver resolver_;
|
||||||
tcp::socket socket_;
|
tcp::socket socket_;
|
||||||
boost::asio::steady_timer timer_;
|
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)
|
boost::beast::flat_buffer buffer_; // (Must persist between reads)
|
||||||
http::request<http::empty_body> req_;
|
http::request<http::empty_body> req_;
|
||||||
http::response<http::string_body> res_;
|
http::response<http::string_body> res_;
|
||||||
@ -156,16 +160,16 @@ class worker : public std::enable_shared_from_this<worker>
|
|||||||
public:
|
public:
|
||||||
worker(worker&&) = default;
|
worker(worker&&) = default;
|
||||||
|
|
||||||
// Resolver and socket require an io_service
|
// Resolver and socket require an io_context
|
||||||
worker(
|
worker(
|
||||||
crawl_report& report,
|
crawl_report& report,
|
||||||
boost::asio::io_service& ios)
|
boost::asio::io_context& ioc)
|
||||||
: report_(report)
|
: report_(report)
|
||||||
, resolver_(ios)
|
, resolver_(ioc)
|
||||||
, socket_(ios)
|
, socket_(ioc)
|
||||||
, timer_(ios,
|
, timer_(ioc,
|
||||||
(chrono::steady_clock::time_point::max)())
|
(chrono::steady_clock::time_point::max)())
|
||||||
, strand_(ios)
|
, strand_(ioc.get_executor())
|
||||||
{
|
{
|
||||||
// Set up the common fields of the request
|
// Set up the common fields of the request
|
||||||
req_.version(11);
|
req_.version(11);
|
||||||
@ -200,7 +204,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Verify that the timer really expired since the deadline may have moved.
|
// 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_.shutdown(tcp::socket::shutdown_both, ec);
|
||||||
socket_.close(ec);
|
socket_.close(ec);
|
||||||
@ -209,10 +213,12 @@ public:
|
|||||||
|
|
||||||
// Wait on the timer
|
// Wait on the timer
|
||||||
timer_.async_wait(
|
timer_.async_wait(
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&worker::on_timer,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1)));
|
&worker::on_timer,
|
||||||
|
shared_from_this(),
|
||||||
|
std::placeholders::_1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -224,8 +230,7 @@ public:
|
|||||||
// nullptr means no more work
|
// nullptr means no more work
|
||||||
if(! host)
|
if(! host)
|
||||||
{
|
{
|
||||||
boost::system::error_code ec;
|
timer_.cancel_one();
|
||||||
timer_.cancel(ec);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,23 +238,26 @@ public:
|
|||||||
req_.set(http::field::host, host);
|
req_.set(http::field::host, host);
|
||||||
|
|
||||||
// Set the timer
|
// Set the timer
|
||||||
timer_.expires_from_now(chrono::seconds(timeout));
|
timer_.expires_after(chrono::seconds(timeout));
|
||||||
|
|
||||||
// Set up an HTTP GET request message
|
// Set up an HTTP GET request message
|
||||||
// Look up the domain name
|
// Look up the domain name
|
||||||
resolver_.async_resolve(
|
resolver_.async_resolve(
|
||||||
tcp::resolver::query{host, "http"},
|
host,
|
||||||
strand_.wrap(std::bind(
|
"http",
|
||||||
&worker::on_resolve,
|
boost::asio::bind_executor(
|
||||||
shared_from_this(),
|
strand_,
|
||||||
std::placeholders::_1,
|
std::bind(
|
||||||
std::placeholders::_2)));
|
&worker::on_resolve,
|
||||||
|
shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
on_resolve(
|
on_resolve(
|
||||||
boost::system::error_code ec,
|
boost::system::error_code ec,
|
||||||
tcp::resolver::iterator result)
|
tcp::resolver::results_type results)
|
||||||
{
|
{
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
@ -262,16 +270,19 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set the timer
|
// 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
|
// Make the connection on the IP address we get from a lookup
|
||||||
boost::asio::async_connect(
|
boost::asio::async_connect(
|
||||||
socket_,
|
socket_,
|
||||||
result,
|
results.begin(),
|
||||||
strand_.wrap(std::bind(
|
results.end(),
|
||||||
&worker::on_connect,
|
boost::asio::bind_executor(
|
||||||
shared_from_this(),
|
strand_,
|
||||||
std::placeholders::_1)));
|
std::bind(
|
||||||
|
&worker::on_connect,
|
||||||
|
shared_from_this(),
|
||||||
|
std::placeholders::_1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -288,17 +299,19 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set the timer
|
// Set the timer
|
||||||
timer_.expires_from_now(chrono::seconds(timeout));
|
timer_.expires_after(chrono::seconds(timeout));
|
||||||
|
|
||||||
// Send the HTTP request to the remote host
|
// Send the HTTP request to the remote host
|
||||||
http::async_write(
|
http::async_write(
|
||||||
socket_,
|
socket_,
|
||||||
req_,
|
req_,
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&worker::on_write,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&worker::on_write,
|
||||||
std::placeholders::_2)));
|
shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -319,18 +332,20 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set the timer
|
// Set the timer
|
||||||
timer_.expires_from_now(chrono::seconds(timeout));
|
timer_.expires_after(chrono::seconds(timeout));
|
||||||
|
|
||||||
// Receive the HTTP response
|
// Receive the HTTP response
|
||||||
http::async_read(
|
http::async_read(
|
||||||
socket_,
|
socket_,
|
||||||
buffer_,
|
buffer_,
|
||||||
res_,
|
res_,
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&worker::on_read,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&worker::on_read,
|
||||||
std::placeholders::_2)));
|
shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -400,41 +415,41 @@ int main(int argc, char* argv[])
|
|||||||
" http-crawl 100 1\n";
|
" http-crawl 100 1\n";
|
||||||
return EXIT_FAILURE;
|
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
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios{1};
|
boost::asio::io_context ioc{1};
|
||||||
|
|
||||||
// The work keeps io_service::run from returning
|
// The work keeps io_context::run from returning
|
||||||
boost::optional<boost::asio::io_service::work> work{ios};
|
auto work = boost::asio::make_work_guard(ioc);
|
||||||
|
|
||||||
// The report holds the aggregated statistics
|
// The report holds the aggregated statistics
|
||||||
crawl_report report{ios};
|
crawl_report report{ioc};
|
||||||
|
|
||||||
timer t;
|
timer t;
|
||||||
|
|
||||||
// Create and launch the worker threads.
|
// Create and launch the worker threads.
|
||||||
std::vector<std::thread> workers;
|
std::vector<std::thread> workers;
|
||||||
workers.reserve(threads + 1);
|
workers.reserve(threads + 1);
|
||||||
for(std::size_t i = 0; i < threads; ++i)
|
for(int i = 0; i < threads; ++i)
|
||||||
workers.emplace_back(
|
workers.emplace_back(
|
||||||
[&report]
|
[&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
|
// 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.
|
// do a lot of name resolutions in parallel.
|
||||||
boost::asio::io_service ios{1};
|
boost::asio::io_context ioc{1};
|
||||||
std::make_shared<worker>(report, ios)->run();
|
std::make_shared<worker>(report, ioc)->run();
|
||||||
ios.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
|
// is used to aggregate the statistics
|
||||||
workers.emplace_back(
|
workers.emplace_back(
|
||||||
[&ios]
|
[&ioc]
|
||||||
{
|
{
|
||||||
ios.run();
|
ioc.run();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Now block until all threads exit
|
// Now block until all threads exit
|
||||||
@ -442,11 +457,10 @@ int main(int argc, char* argv[])
|
|||||||
{
|
{
|
||||||
auto& thread = workers[i];
|
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.
|
// work object so that it can return from run.
|
||||||
//if(&thread == &workers.back())
|
|
||||||
if(i == workers.size() - 1)
|
if(i == workers.size() - 1)
|
||||||
work = boost::none;
|
work.reset();
|
||||||
|
|
||||||
// Wait for the thread to exit
|
// Wait for the thread to exit
|
||||||
thread.join();
|
thread.join();
|
||||||
|
@ -47,8 +47,8 @@ int main(int argc, char** argv)
|
|||||||
auto const port = argv[2];
|
auto const port = argv[2];
|
||||||
auto const target = argv[3];
|
auto const target = argv[3];
|
||||||
|
|
||||||
// The io_service is required for all I/O
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios;
|
boost::asio::io_context ioc;
|
||||||
|
|
||||||
// The SSL context is required, and holds certificates
|
// The SSL context is required, and holds certificates
|
||||||
ssl::context ctx{ssl::context::sslv23_client};
|
ssl::context ctx{ssl::context::sslv23_client};
|
||||||
@ -57,14 +57,14 @@ int main(int argc, char** argv)
|
|||||||
load_root_certificates(ctx);
|
load_root_certificates(ctx);
|
||||||
|
|
||||||
// These objects perform our I/O
|
// These objects perform our I/O
|
||||||
tcp::resolver resolver{ios};
|
tcp::resolver resolver{ioc};
|
||||||
ssl::stream<tcp::socket> stream{ios, ctx};
|
ssl::stream<tcp::socket> stream{ioc, ctx};
|
||||||
|
|
||||||
// Look up the domain name
|
// 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
|
// 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
|
// Perform the SSL handshake
|
||||||
stream.handshake(ssl::stream_base::client);
|
stream.handshake(ssl::stream_base::client);
|
||||||
|
@ -45,18 +45,18 @@ int main(int argc, char** argv)
|
|||||||
auto const port = argv[2];
|
auto const port = argv[2];
|
||||||
auto const target = argv[3];
|
auto const target = argv[3];
|
||||||
|
|
||||||
// The io_service is required for all I/O
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios;
|
boost::asio::io_context ioc;
|
||||||
|
|
||||||
// These objects perform our I/O
|
// These objects perform our I/O
|
||||||
tcp::resolver resolver{ios};
|
tcp::resolver resolver{ioc};
|
||||||
tcp::socket socket{ios};
|
tcp::socket socket{ioc};
|
||||||
|
|
||||||
// Look up the domain name
|
// 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
|
// 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
|
// Set up an HTTP GET request message
|
||||||
http::request<http::string_body> req{http::verb::get, target, 11};
|
http::request<http::string_body> req{http::verb::get, target, 11};
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include <boost/beast/core.hpp>
|
#include <boost/beast/core.hpp>
|
||||||
#include <boost/beast/http.hpp>
|
#include <boost/beast/http.hpp>
|
||||||
#include <boost/beast/version.hpp>
|
#include <boost/beast/version.hpp>
|
||||||
|
#include <boost/asio/bind_executor.hpp>
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
#include <boost/asio/ssl/stream.hpp>
|
#include <boost/asio/ssl/stream.hpp>
|
||||||
#include <boost/asio/strand.hpp>
|
#include <boost/asio/strand.hpp>
|
||||||
@ -244,18 +245,21 @@ class session : public std::enable_shared_from_this<session>
|
|||||||
http::async_write(
|
http::async_write(
|
||||||
self_.stream_,
|
self_.stream_,
|
||||||
*sp,
|
*sp,
|
||||||
self_.strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::on_write,
|
self_.strand_,
|
||||||
self_.shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&session::on_write,
|
||||||
std::placeholders::_2,
|
self_.shared_from_this(),
|
||||||
! sp->keep_alive())));
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2,
|
||||||
|
! sp->keep_alive())));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
tcp::socket socket_;
|
tcp::socket socket_;
|
||||||
ssl::stream<tcp::socket&> stream_;
|
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_;
|
boost::beast::flat_buffer buffer_;
|
||||||
std::string const& doc_root_;
|
std::string const& doc_root_;
|
||||||
http::request<http::string_body> req_;
|
http::request<http::string_body> req_;
|
||||||
@ -271,7 +275,7 @@ public:
|
|||||||
std::string const& doc_root)
|
std::string const& doc_root)
|
||||||
: socket_(std::move(socket))
|
: socket_(std::move(socket))
|
||||||
, stream_(socket_, ctx)
|
, stream_(socket_, ctx)
|
||||||
, strand_(socket_.get_io_service())
|
, strand_(socket_.get_executor())
|
||||||
, doc_root_(doc_root)
|
, doc_root_(doc_root)
|
||||||
, lambda_(*this)
|
, lambda_(*this)
|
||||||
{
|
{
|
||||||
@ -284,10 +288,12 @@ public:
|
|||||||
// Perform the SSL handshake
|
// Perform the SSL handshake
|
||||||
stream_.async_handshake(
|
stream_.async_handshake(
|
||||||
ssl::stream_base::server,
|
ssl::stream_base::server,
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::on_handshake,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1)));
|
&session::on_handshake,
|
||||||
|
shared_from_this(),
|
||||||
|
std::placeholders::_1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -304,11 +310,13 @@ public:
|
|||||||
{
|
{
|
||||||
// Read a request
|
// Read a request
|
||||||
http::async_read(stream_, buffer_, req_,
|
http::async_read(stream_, buffer_, req_,
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::on_read,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&session::on_read,
|
||||||
std::placeholders::_2)));
|
shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -359,10 +367,12 @@ public:
|
|||||||
{
|
{
|
||||||
// Perform the SSL shutdown
|
// Perform the SSL shutdown
|
||||||
stream_.async_shutdown(
|
stream_.async_shutdown(
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::on_shutdown,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1)));
|
&session::on_shutdown,
|
||||||
|
shared_from_this(),
|
||||||
|
std::placeholders::_1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -387,13 +397,13 @@ class listener : public std::enable_shared_from_this<listener>
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
listener(
|
listener(
|
||||||
boost::asio::io_service& ios,
|
boost::asio::io_context& ioc,
|
||||||
ssl::context& ctx,
|
ssl::context& ctx,
|
||||||
tcp::endpoint endpoint,
|
tcp::endpoint endpoint,
|
||||||
std::string const& doc_root)
|
std::string const& doc_root)
|
||||||
: ctx_(ctx)
|
: ctx_(ctx)
|
||||||
, acceptor_(ios)
|
, acceptor_(ioc)
|
||||||
, socket_(ios)
|
, socket_(ioc)
|
||||||
, doc_root_(doc_root)
|
, doc_root_(doc_root)
|
||||||
{
|
{
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
@ -416,7 +426,7 @@ public:
|
|||||||
|
|
||||||
// Start listening for connections
|
// Start listening for connections
|
||||||
acceptor_.listen(
|
acceptor_.listen(
|
||||||
boost::asio::socket_base::max_connections, ec);
|
boost::asio::socket_base::max_listen_connections, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
fail(ec, "listen");
|
fail(ec, "listen");
|
||||||
@ -478,13 +488,13 @@ int main(int argc, char* argv[])
|
|||||||
" http-server-async-ssl 0.0.0.0 8080 . 1\n";
|
" http-server-async-ssl 0.0.0.0 8080 . 1\n";
|
||||||
return EXIT_FAILURE;
|
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 port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||||
std::string const doc_root = argv[3];
|
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
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios{threads};
|
boost::asio::io_context ioc{threads};
|
||||||
|
|
||||||
// The SSL context is required, and holds certificates
|
// The SSL context is required, and holds certificates
|
||||||
ssl::context ctx{ssl::context::sslv23};
|
ssl::context ctx{ssl::context::sslv23};
|
||||||
@ -494,7 +504,7 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
// Create and launch a listening port
|
// Create and launch a listening port
|
||||||
std::make_shared<listener>(
|
std::make_shared<listener>(
|
||||||
ios,
|
ioc,
|
||||||
ctx,
|
ctx,
|
||||||
tcp::endpoint{address, port},
|
tcp::endpoint{address, port},
|
||||||
doc_root)->run();
|
doc_root)->run();
|
||||||
@ -504,11 +514,11 @@ int main(int argc, char* argv[])
|
|||||||
v.reserve(threads - 1);
|
v.reserve(threads - 1);
|
||||||
for(auto i = threads - 1; i > 0; --i)
|
for(auto i = threads - 1; i > 0; --i)
|
||||||
v.emplace_back(
|
v.emplace_back(
|
||||||
[&ios]
|
[&ioc]
|
||||||
{
|
{
|
||||||
ios.run();
|
ioc.run();
|
||||||
});
|
});
|
||||||
ios.run();
|
ioc.run();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <boost/beast/core.hpp>
|
#include <boost/beast/core.hpp>
|
||||||
#include <boost/beast/http.hpp>
|
#include <boost/beast/http.hpp>
|
||||||
#include <boost/beast/version.hpp>
|
#include <boost/beast/version.hpp>
|
||||||
|
#include <boost/asio/bind_executor.hpp>
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
#include <boost/asio/strand.hpp>
|
#include <boost/asio/strand.hpp>
|
||||||
#include <boost/config.hpp>
|
#include <boost/config.hpp>
|
||||||
@ -240,17 +241,20 @@ class session : public std::enable_shared_from_this<session>
|
|||||||
http::async_write(
|
http::async_write(
|
||||||
self_.socket_,
|
self_.socket_,
|
||||||
*sp,
|
*sp,
|
||||||
self_.strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::on_write,
|
self_.strand_,
|
||||||
self_.shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&session::on_write,
|
||||||
std::placeholders::_2,
|
self_.shared_from_this(),
|
||||||
! sp->keep_alive())));
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2,
|
||||||
|
! sp->keep_alive())));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
tcp::socket socket_;
|
tcp::socket socket_;
|
||||||
boost::asio::io_service::strand strand_;
|
boost::asio::strand<
|
||||||
|
boost::asio::io_context::executor_type> strand_;
|
||||||
boost::beast::flat_buffer buffer_;
|
boost::beast::flat_buffer buffer_;
|
||||||
std::string const& doc_root_;
|
std::string const& doc_root_;
|
||||||
http::request<http::string_body> req_;
|
http::request<http::string_body> req_;
|
||||||
@ -264,7 +268,7 @@ public:
|
|||||||
tcp::socket socket,
|
tcp::socket socket,
|
||||||
std::string const& doc_root)
|
std::string const& doc_root)
|
||||||
: socket_(std::move(socket))
|
: socket_(std::move(socket))
|
||||||
, strand_(socket_.get_io_service())
|
, strand_(socket_.get_executor())
|
||||||
, doc_root_(doc_root)
|
, doc_root_(doc_root)
|
||||||
, lambda_(*this)
|
, lambda_(*this)
|
||||||
{
|
{
|
||||||
@ -282,11 +286,13 @@ public:
|
|||||||
{
|
{
|
||||||
// Read a request
|
// Read a request
|
||||||
http::async_read(socket_, buffer_, req_,
|
http::async_read(socket_, buffer_, req_,
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::on_read,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&session::on_read,
|
||||||
std::placeholders::_2)));
|
shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -354,11 +360,11 @@ class listener : public std::enable_shared_from_this<listener>
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
listener(
|
listener(
|
||||||
boost::asio::io_service& ios,
|
boost::asio::io_context& ioc,
|
||||||
tcp::endpoint endpoint,
|
tcp::endpoint endpoint,
|
||||||
std::string const& doc_root)
|
std::string const& doc_root)
|
||||||
: acceptor_(ios)
|
: acceptor_(ioc)
|
||||||
, socket_(ios)
|
, socket_(ioc)
|
||||||
, doc_root_(doc_root)
|
, doc_root_(doc_root)
|
||||||
{
|
{
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
@ -381,7 +387,7 @@ public:
|
|||||||
|
|
||||||
// Start listening for connections
|
// Start listening for connections
|
||||||
acceptor_.listen(
|
acceptor_.listen(
|
||||||
boost::asio::socket_base::max_connections, ec);
|
boost::asio::socket_base::max_listen_connections, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
fail(ec, "listen");
|
fail(ec, "listen");
|
||||||
@ -442,17 +448,17 @@ int main(int argc, char* argv[])
|
|||||||
" http-server-async 0.0.0.0 8080 . 1\n";
|
" http-server-async 0.0.0.0 8080 . 1\n";
|
||||||
return EXIT_FAILURE;
|
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 port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||||
std::string const doc_root = argv[3];
|
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
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios{threads};
|
boost::asio::io_context ioc{threads};
|
||||||
|
|
||||||
// Create and launch a listening port
|
// Create and launch a listening port
|
||||||
std::make_shared<listener>(
|
std::make_shared<listener>(
|
||||||
ios,
|
ioc,
|
||||||
tcp::endpoint{address, port},
|
tcp::endpoint{address, port},
|
||||||
doc_root)->run();
|
doc_root)->run();
|
||||||
|
|
||||||
@ -461,11 +467,11 @@ int main(int argc, char* argv[])
|
|||||||
v.reserve(threads - 1);
|
v.reserve(threads - 1);
|
||||||
for(auto i = threads - 1; i > 0; --i)
|
for(auto i = threads - 1; i > 0; --i)
|
||||||
v.emplace_back(
|
v.emplace_back(
|
||||||
[&ios]
|
[&ioc]
|
||||||
{
|
{
|
||||||
ios.run();
|
ioc.run();
|
||||||
});
|
});
|
||||||
ios.run();
|
ioc.run();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -308,7 +308,7 @@ do_session(
|
|||||||
// Accepts incoming connections and launches the sessions
|
// Accepts incoming connections and launches the sessions
|
||||||
void
|
void
|
||||||
do_listen(
|
do_listen(
|
||||||
boost::asio::io_service& ios,
|
boost::asio::io_context& ioc,
|
||||||
ssl::context& ctx,
|
ssl::context& ctx,
|
||||||
tcp::endpoint endpoint,
|
tcp::endpoint endpoint,
|
||||||
std::string const& doc_root,
|
std::string const& doc_root,
|
||||||
@ -317,7 +317,7 @@ do_listen(
|
|||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
|
|
||||||
// Open the acceptor
|
// Open the acceptor
|
||||||
tcp::acceptor acceptor(ios);
|
tcp::acceptor acceptor(ioc);
|
||||||
acceptor.open(endpoint.protocol(), ec);
|
acceptor.open(endpoint.protocol(), ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return fail(ec, "open");
|
return fail(ec, "open");
|
||||||
@ -328,19 +328,19 @@ do_listen(
|
|||||||
return fail(ec, "bind");
|
return fail(ec, "bind");
|
||||||
|
|
||||||
// Start listening for connections
|
// 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)
|
if(ec)
|
||||||
return fail(ec, "listen");
|
return fail(ec, "listen");
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
tcp::socket socket(ios);
|
tcp::socket socket(ioc);
|
||||||
acceptor.async_accept(socket, yield[ec]);
|
acceptor.async_accept(socket, yield[ec]);
|
||||||
if(ec)
|
if(ec)
|
||||||
fail(ec, "accept");
|
fail(ec, "accept");
|
||||||
else
|
else
|
||||||
boost::asio::spawn(
|
boost::asio::spawn(
|
||||||
acceptor.get_io_service(),
|
acceptor.get_executor().context(),
|
||||||
std::bind(
|
std::bind(
|
||||||
&do_session,
|
&do_session,
|
||||||
std::move(socket),
|
std::move(socket),
|
||||||
@ -361,13 +361,13 @@ int main(int argc, char* argv[])
|
|||||||
" http-server-coro-ssl 0.0.0.0 8080 . 1\n";
|
" http-server-coro-ssl 0.0.0.0 8080 . 1\n";
|
||||||
return EXIT_FAILURE;
|
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 port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||||
std::string const doc_root = argv[3];
|
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
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios{threads};
|
boost::asio::io_context ioc{threads};
|
||||||
|
|
||||||
// The SSL context is required, and holds certificates
|
// The SSL context is required, and holds certificates
|
||||||
ssl::context ctx{ssl::context::sslv23};
|
ssl::context ctx{ssl::context::sslv23};
|
||||||
@ -376,10 +376,10 @@ int main(int argc, char* argv[])
|
|||||||
load_server_certificate(ctx);
|
load_server_certificate(ctx);
|
||||||
|
|
||||||
// Spawn a listening port
|
// Spawn a listening port
|
||||||
boost::asio::spawn(ios,
|
boost::asio::spawn(ioc,
|
||||||
std::bind(
|
std::bind(
|
||||||
&do_listen,
|
&do_listen,
|
||||||
std::ref(ios),
|
std::ref(ioc),
|
||||||
std::ref(ctx),
|
std::ref(ctx),
|
||||||
tcp::endpoint{address, port},
|
tcp::endpoint{address, port},
|
||||||
doc_root,
|
doc_root,
|
||||||
@ -390,11 +390,11 @@ int main(int argc, char* argv[])
|
|||||||
v.reserve(threads - 1);
|
v.reserve(threads - 1);
|
||||||
for(auto i = threads - 1; i > 0; --i)
|
for(auto i = threads - 1; i > 0; --i)
|
||||||
v.emplace_back(
|
v.emplace_back(
|
||||||
[&ios]
|
[&ioc]
|
||||||
{
|
{
|
||||||
ios.run();
|
ioc.run();
|
||||||
});
|
});
|
||||||
ios.run();
|
ioc.run();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -293,7 +293,7 @@ do_session(
|
|||||||
// Accepts incoming connections and launches the sessions
|
// Accepts incoming connections and launches the sessions
|
||||||
void
|
void
|
||||||
do_listen(
|
do_listen(
|
||||||
boost::asio::io_service& ios,
|
boost::asio::io_context& ioc,
|
||||||
tcp::endpoint endpoint,
|
tcp::endpoint endpoint,
|
||||||
std::string const& doc_root,
|
std::string const& doc_root,
|
||||||
boost::asio::yield_context yield)
|
boost::asio::yield_context yield)
|
||||||
@ -301,7 +301,7 @@ do_listen(
|
|||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
|
|
||||||
// Open the acceptor
|
// Open the acceptor
|
||||||
tcp::acceptor acceptor(ios);
|
tcp::acceptor acceptor(ioc);
|
||||||
acceptor.open(endpoint.protocol(), ec);
|
acceptor.open(endpoint.protocol(), ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return fail(ec, "open");
|
return fail(ec, "open");
|
||||||
@ -312,19 +312,19 @@ do_listen(
|
|||||||
return fail(ec, "bind");
|
return fail(ec, "bind");
|
||||||
|
|
||||||
// Start listening for connections
|
// 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)
|
if(ec)
|
||||||
return fail(ec, "listen");
|
return fail(ec, "listen");
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
tcp::socket socket(ios);
|
tcp::socket socket(ioc);
|
||||||
acceptor.async_accept(socket, yield[ec]);
|
acceptor.async_accept(socket, yield[ec]);
|
||||||
if(ec)
|
if(ec)
|
||||||
fail(ec, "accept");
|
fail(ec, "accept");
|
||||||
else
|
else
|
||||||
boost::asio::spawn(
|
boost::asio::spawn(
|
||||||
acceptor.get_io_service(),
|
acceptor.get_executor().context(),
|
||||||
std::bind(
|
std::bind(
|
||||||
&do_session,
|
&do_session,
|
||||||
std::move(socket),
|
std::move(socket),
|
||||||
@ -344,19 +344,19 @@ int main(int argc, char* argv[])
|
|||||||
" http-server-coro 0.0.0.0 8080 . 1\n";
|
" http-server-coro 0.0.0.0 8080 . 1\n";
|
||||||
return EXIT_FAILURE;
|
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 port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||||
std::string const doc_root = argv[3];
|
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
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios{threads};
|
boost::asio::io_context ioc{threads};
|
||||||
|
|
||||||
// Spawn a listening port
|
// Spawn a listening port
|
||||||
boost::asio::spawn(ios,
|
boost::asio::spawn(ioc,
|
||||||
std::bind(
|
std::bind(
|
||||||
&do_listen,
|
&do_listen,
|
||||||
std::ref(ios),
|
std::ref(ioc),
|
||||||
tcp::endpoint{address, port},
|
tcp::endpoint{address, port},
|
||||||
doc_root,
|
doc_root,
|
||||||
std::placeholders::_1));
|
std::placeholders::_1));
|
||||||
@ -366,11 +366,11 @@ int main(int argc, char* argv[])
|
|||||||
v.reserve(threads - 1);
|
v.reserve(threads - 1);
|
||||||
for(auto i = threads - 1; i > 0; --i)
|
for(auto i = threads - 1; i > 0; --i)
|
||||||
v.emplace_back(
|
v.emplace_back(
|
||||||
[&ios]
|
[&ioc]
|
||||||
{
|
{
|
||||||
ios.run();
|
ioc.run();
|
||||||
});
|
});
|
||||||
ios.run();
|
ioc.run();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ private:
|
|||||||
std::string doc_root_;
|
std::string doc_root_;
|
||||||
|
|
||||||
// The socket for the currently connected client.
|
// 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
|
// The buffer for performing reads
|
||||||
boost::beast::flat_static_buffer<8192> buffer_;
|
boost::beast::flat_static_buffer<8192> buffer_;
|
||||||
@ -110,7 +110,7 @@ private:
|
|||||||
|
|
||||||
// The timer putting a time limit on requests.
|
// The timer putting a time limit on requests.
|
||||||
boost::asio::basic_waitable_timer<std::chrono::steady_clock> request_deadline_{
|
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.
|
// The string-based response message.
|
||||||
boost::optional<http::response<http::string_body, http::basic_fields<alloc_t>>> string_response_;
|
boost::optional<http::response<http::string_body, http::basic_fields<alloc_t>>> string_response_;
|
||||||
@ -142,7 +142,7 @@ private:
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Request must be fully processed within 60 seconds.
|
// Request must be fully processed within 60 seconds.
|
||||||
request_deadline_.expires_from_now(
|
request_deadline_.expires_after(
|
||||||
std::chrono::seconds(60));
|
std::chrono::seconds(60));
|
||||||
|
|
||||||
read_request();
|
read_request();
|
||||||
@ -288,7 +288,7 @@ private:
|
|||||||
void check_deadline()
|
void check_deadline()
|
||||||
{
|
{
|
||||||
// The deadline may have moved, so check it has really passed.
|
// 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.
|
// Close socket to cancel any outstanding operation.
|
||||||
boost::beast::error_code ec;
|
boost::beast::error_code ec;
|
||||||
@ -322,14 +322,14 @@ int main(int argc, char* argv[])
|
|||||||
return EXIT_FAILURE;
|
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]));
|
unsigned short port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||||
std::string doc_root = argv[3];
|
std::string doc_root = argv[3];
|
||||||
int num_workers = std::atoi(argv[4]);
|
int num_workers = std::atoi(argv[4]);
|
||||||
bool spin = (std::strcmp(argv[5], "spin") == 0);
|
bool spin = (std::strcmp(argv[5], "spin") == 0);
|
||||||
|
|
||||||
boost::asio::io_service ios{1};
|
boost::asio::io_context ioc{1};
|
||||||
tcp::acceptor acceptor{ios, {address, port}};
|
tcp::acceptor acceptor{ioc, {address, port}};
|
||||||
|
|
||||||
std::list<http_worker> workers;
|
std::list<http_worker> workers;
|
||||||
for (int i = 0; i < num_workers; ++i)
|
for (int i = 0; i < num_workers; ++i)
|
||||||
@ -339,9 +339,9 @@ int main(int argc, char* argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (spin)
|
if (spin)
|
||||||
for (;;) ios.poll();
|
for (;;) ioc.poll();
|
||||||
else
|
else
|
||||||
ios.run();
|
ioc.run();
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <boost/beast/core.hpp>
|
#include <boost/beast/core.hpp>
|
||||||
#include <boost/beast/http.hpp>
|
#include <boost/beast/http.hpp>
|
||||||
#include <boost/beast/version.hpp>
|
#include <boost/beast/version.hpp>
|
||||||
|
#include <boost/asio/bind_executor.hpp>
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
#include <boost/asio/ssl/stream.hpp>
|
#include <boost/asio/ssl/stream.hpp>
|
||||||
#include <boost/asio/strand.hpp>
|
#include <boost/asio/strand.hpp>
|
||||||
@ -255,12 +256,14 @@ class session
|
|||||||
http::async_write(
|
http::async_write(
|
||||||
self_.derived().stream(),
|
self_.derived().stream(),
|
||||||
*sp,
|
*sp,
|
||||||
self_.strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::on_write,
|
self_.strand_,
|
||||||
self_.derived().shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&session::on_write,
|
||||||
std::placeholders::_2,
|
self_.derived().shared_from_this(),
|
||||||
! sp->keep_alive())));
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2,
|
||||||
|
! sp->keep_alive())));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -270,19 +273,20 @@ class session
|
|||||||
send_lambda lambda_;
|
send_lambda lambda_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
boost::asio::io_service::strand strand_;
|
boost::asio::strand<
|
||||||
|
boost::asio::io_context::executor_type> strand_;
|
||||||
boost::beast::flat_buffer buffer_;
|
boost::beast::flat_buffer buffer_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Take ownership of the buffer
|
// Take ownership of the buffer
|
||||||
explicit
|
explicit
|
||||||
session(
|
session(
|
||||||
boost::asio::io_service& ios,
|
boost::asio::io_context& ioc,
|
||||||
boost::beast::flat_buffer buffer,
|
boost::beast::flat_buffer buffer,
|
||||||
std::string const& doc_root)
|
std::string const& doc_root)
|
||||||
: doc_root_(doc_root)
|
: doc_root_(doc_root)
|
||||||
, lambda_(*this)
|
, lambda_(*this)
|
||||||
, strand_(ios)
|
, strand_(ioc.get_executor())
|
||||||
, buffer_(std::move(buffer))
|
, buffer_(std::move(buffer))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -295,11 +299,13 @@ public:
|
|||||||
derived().stream(),
|
derived().stream(),
|
||||||
buffer_,
|
buffer_,
|
||||||
req_,
|
req_,
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::on_read,
|
strand_,
|
||||||
derived().shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&session::on_read,
|
||||||
std::placeholders::_2)));
|
derived().shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -352,7 +358,8 @@ class plain_session
|
|||||||
, public std::enable_shared_from_this<plain_session>
|
, public std::enable_shared_from_this<plain_session>
|
||||||
{
|
{
|
||||||
tcp::socket socket_;
|
tcp::socket socket_;
|
||||||
boost::asio::io_service::strand strand_;
|
boost::asio::strand<
|
||||||
|
boost::asio::io_context::executor_type> strand_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Create the session
|
// Create the session
|
||||||
@ -361,11 +368,11 @@ public:
|
|||||||
boost::beast::flat_buffer buffer,
|
boost::beast::flat_buffer buffer,
|
||||||
std::string const& doc_root)
|
std::string const& doc_root)
|
||||||
: session<plain_session>(
|
: session<plain_session>(
|
||||||
socket.get_io_service(),
|
socket.get_executor().context(),
|
||||||
std::move(buffer),
|
std::move(buffer),
|
||||||
doc_root)
|
doc_root)
|
||||||
, socket_(std::move(socket))
|
, socket_(std::move(socket))
|
||||||
, strand_(socket_.get_io_service())
|
, strand_(socket_.get_executor())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -401,7 +408,8 @@ class ssl_session
|
|||||||
{
|
{
|
||||||
tcp::socket socket_;
|
tcp::socket socket_;
|
||||||
ssl::stream<tcp::socket&> stream_;
|
ssl::stream<tcp::socket&> stream_;
|
||||||
boost::asio::io_service::strand strand_;
|
boost::asio::strand<
|
||||||
|
boost::asio::io_context::executor_type> strand_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Create the session
|
// Create the session
|
||||||
@ -411,12 +419,12 @@ public:
|
|||||||
boost::beast::flat_buffer buffer,
|
boost::beast::flat_buffer buffer,
|
||||||
std::string const& doc_root)
|
std::string const& doc_root)
|
||||||
: session<ssl_session>(
|
: session<ssl_session>(
|
||||||
socket.get_io_service(),
|
socket.get_executor().context(),
|
||||||
std::move(buffer),
|
std::move(buffer),
|
||||||
doc_root)
|
doc_root)
|
||||||
, socket_(std::move(socket))
|
, socket_(std::move(socket))
|
||||||
, stream_(socket_, ctx)
|
, stream_(socket_, ctx)
|
||||||
, strand_(stream_.get_io_service())
|
, strand_(stream_.get_executor())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -436,11 +444,13 @@ public:
|
|||||||
stream_.async_handshake(
|
stream_.async_handshake(
|
||||||
ssl::stream_base::server,
|
ssl::stream_base::server,
|
||||||
buffer_.data(),
|
buffer_.data(),
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&ssl_session::on_handshake,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&ssl_session::on_handshake,
|
||||||
std::placeholders::_2)));
|
shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2)));
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
on_handshake(
|
on_handshake(
|
||||||
@ -461,10 +471,12 @@ public:
|
|||||||
{
|
{
|
||||||
// Perform the SSL shutdown
|
// Perform the SSL shutdown
|
||||||
stream_.async_shutdown(
|
stream_.async_shutdown(
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&ssl_session::on_shutdown,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1)));
|
&ssl_session::on_shutdown,
|
||||||
|
shared_from_this(),
|
||||||
|
std::placeholders::_1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -484,7 +496,8 @@ class detect_session : public std::enable_shared_from_this<detect_session>
|
|||||||
{
|
{
|
||||||
tcp::socket socket_;
|
tcp::socket socket_;
|
||||||
ssl::context& ctx_;
|
ssl::context& ctx_;
|
||||||
boost::asio::io_service::strand strand_;
|
boost::asio::strand<
|
||||||
|
boost::asio::io_context::executor_type> strand_;
|
||||||
std::string const& doc_root_;
|
std::string const& doc_root_;
|
||||||
boost::beast::flat_buffer buffer_;
|
boost::beast::flat_buffer buffer_;
|
||||||
|
|
||||||
@ -496,7 +509,7 @@ public:
|
|||||||
std::string const& doc_root)
|
std::string const& doc_root)
|
||||||
: socket_(std::move(socket))
|
: socket_(std::move(socket))
|
||||||
, ctx_(ctx)
|
, ctx_(ctx)
|
||||||
, strand_(socket_.get_io_service())
|
, strand_(socket_.get_executor())
|
||||||
, doc_root_(doc_root)
|
, doc_root_(doc_root)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -508,11 +521,13 @@ public:
|
|||||||
async_detect_ssl(
|
async_detect_ssl(
|
||||||
socket_,
|
socket_,
|
||||||
buffer_,
|
buffer_,
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&detect_session::on_detect,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&detect_session::on_detect,
|
||||||
std::placeholders::_2)));
|
shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -545,21 +560,22 @@ public:
|
|||||||
class listener : public std::enable_shared_from_this<listener>
|
class listener : public std::enable_shared_from_this<listener>
|
||||||
{
|
{
|
||||||
ssl::context& ctx_;
|
ssl::context& ctx_;
|
||||||
boost::asio::io_service::strand strand_;
|
boost::asio::strand<
|
||||||
|
boost::asio::io_context::executor_type> strand_;
|
||||||
tcp::acceptor acceptor_;
|
tcp::acceptor acceptor_;
|
||||||
tcp::socket socket_;
|
tcp::socket socket_;
|
||||||
std::string const& doc_root_;
|
std::string const& doc_root_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
listener(
|
listener(
|
||||||
boost::asio::io_service& ios,
|
boost::asio::io_context& ioc,
|
||||||
ssl::context& ctx,
|
ssl::context& ctx,
|
||||||
tcp::endpoint endpoint,
|
tcp::endpoint endpoint,
|
||||||
std::string const& doc_root)
|
std::string const& doc_root)
|
||||||
: ctx_(ctx)
|
: ctx_(ctx)
|
||||||
, strand_(ios)
|
, strand_(ioc.get_executor())
|
||||||
, acceptor_(ios)
|
, acceptor_(ioc)
|
||||||
, socket_(ios)
|
, socket_(ioc)
|
||||||
, doc_root_(doc_root)
|
, doc_root_(doc_root)
|
||||||
{
|
{
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
@ -582,7 +598,7 @@ public:
|
|||||||
|
|
||||||
// Start listening for connections
|
// Start listening for connections
|
||||||
acceptor_.listen(
|
acceptor_.listen(
|
||||||
boost::asio::socket_base::max_connections, ec);
|
boost::asio::socket_base::max_listen_connections, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
fail(ec, "listen");
|
fail(ec, "listen");
|
||||||
@ -644,13 +660,13 @@ int main(int argc, char* argv[])
|
|||||||
" http-server-sync 0.0.0.0 8080 .\n";
|
" http-server-sync 0.0.0.0 8080 .\n";
|
||||||
return EXIT_FAILURE;
|
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 port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||||
std::string const doc_root = argv[3];
|
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
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios{threads};
|
boost::asio::io_context ioc{threads};
|
||||||
|
|
||||||
// The SSL context is required, and holds certificates
|
// The SSL context is required, and holds certificates
|
||||||
ssl::context ctx{ssl::context::sslv23};
|
ssl::context ctx{ssl::context::sslv23};
|
||||||
@ -660,7 +676,7 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
// Create and launch a listening port
|
// Create and launch a listening port
|
||||||
std::make_shared<listener>(
|
std::make_shared<listener>(
|
||||||
ios,
|
ioc,
|
||||||
ctx,
|
ctx,
|
||||||
tcp::endpoint{address, port},
|
tcp::endpoint{address, port},
|
||||||
doc_root)->run();
|
doc_root)->run();
|
||||||
@ -670,11 +686,11 @@ int main(int argc, char* argv[])
|
|||||||
v.reserve(threads - 1);
|
v.reserve(threads - 1);
|
||||||
for(auto i = threads - 1; i > 0; --i)
|
for(auto i = threads - 1; i > 0; --i)
|
||||||
v.emplace_back(
|
v.emplace_back(
|
||||||
[&ios]
|
[&ioc]
|
||||||
{
|
{
|
||||||
ios.run();
|
ioc.run();
|
||||||
});
|
});
|
||||||
ios.run();
|
ioc.run();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ private:
|
|||||||
|
|
||||||
// The timer for putting a deadline on connection processing.
|
// The timer for putting a deadline on connection processing.
|
||||||
boost::asio::basic_waitable_timer<std::chrono::steady_clock> deadline_{
|
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.
|
// Asynchronously receive a complete request message.
|
||||||
void
|
void
|
||||||
@ -231,16 +231,16 @@ main(int argc, char* argv[])
|
|||||||
return EXIT_FAILURE;
|
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]));
|
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::acceptor acceptor{ioc, {address, port}};
|
||||||
tcp::socket socket{ios};
|
tcp::socket socket{ioc};
|
||||||
http_server(acceptor, socket);
|
http_server(acceptor, socket);
|
||||||
|
|
||||||
ios.run();
|
ioc.run();
|
||||||
}
|
}
|
||||||
catch(std::exception const& e)
|
catch(std::exception const& e)
|
||||||
{
|
{
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include <boost/beast/core.hpp>
|
#include <boost/beast/core.hpp>
|
||||||
#include <boost/beast/http.hpp>
|
#include <boost/beast/http.hpp>
|
||||||
#include <boost/beast/version.hpp>
|
#include <boost/beast/version.hpp>
|
||||||
|
#include <boost/asio/bind_executor.hpp>
|
||||||
#include <boost/asio/coroutine.hpp>
|
#include <boost/asio/coroutine.hpp>
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
#include <boost/asio/ssl/stream.hpp>
|
#include <boost/asio/ssl/stream.hpp>
|
||||||
@ -247,18 +248,21 @@ class session
|
|||||||
http::async_write(
|
http::async_write(
|
||||||
self_.socket_,
|
self_.socket_,
|
||||||
*sp,
|
*sp,
|
||||||
self_.strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::loop,
|
self_.strand_,
|
||||||
self_.shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&session::loop,
|
||||||
std::placeholders::_2,
|
self_.shared_from_this(),
|
||||||
! sp->keep_alive())));
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2,
|
||||||
|
! sp->keep_alive())));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
tcp::socket socket_;
|
tcp::socket socket_;
|
||||||
ssl::stream<tcp::socket&> stream_;
|
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_;
|
boost::beast::flat_buffer buffer_;
|
||||||
std::string const& doc_root_;
|
std::string const& doc_root_;
|
||||||
http::request<http::string_body> req_;
|
http::request<http::string_body> req_;
|
||||||
@ -274,7 +278,7 @@ public:
|
|||||||
std::string const& doc_root)
|
std::string const& doc_root)
|
||||||
: socket_(std::move(socket))
|
: socket_(std::move(socket))
|
||||||
, stream_(socket_, ctx)
|
, stream_(socket_, ctx)
|
||||||
, strand_(socket_.get_io_service())
|
, strand_(socket_.get_executor())
|
||||||
, doc_root_(doc_root)
|
, doc_root_(doc_root)
|
||||||
, lambda_(*this)
|
, lambda_(*this)
|
||||||
{
|
{
|
||||||
@ -300,12 +304,14 @@ public:
|
|||||||
// Perform the SSL handshake
|
// Perform the SSL handshake
|
||||||
yield stream_.async_handshake(
|
yield stream_.async_handshake(
|
||||||
ssl::stream_base::server,
|
ssl::stream_base::server,
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::loop,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&session::loop,
|
||||||
0,
|
shared_from_this(),
|
||||||
false)));
|
std::placeholders::_1,
|
||||||
|
0,
|
||||||
|
false)));
|
||||||
if(ec)
|
if(ec)
|
||||||
return fail(ec, "handshake");
|
return fail(ec, "handshake");
|
||||||
|
|
||||||
@ -313,12 +319,14 @@ public:
|
|||||||
{
|
{
|
||||||
// Read a request
|
// Read a request
|
||||||
yield http::async_read(stream_, buffer_, req_,
|
yield http::async_read(stream_, buffer_, req_,
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::loop,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&session::loop,
|
||||||
std::placeholders::_2,
|
shared_from_this(),
|
||||||
false)));
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2,
|
||||||
|
false)));
|
||||||
if(ec == http::error::end_of_stream)
|
if(ec == http::error::end_of_stream)
|
||||||
{
|
{
|
||||||
// The remote host closed the connection
|
// The remote host closed the connection
|
||||||
@ -344,12 +352,14 @@ public:
|
|||||||
|
|
||||||
// Perform the SSL shutdown
|
// Perform the SSL shutdown
|
||||||
yield stream_.async_shutdown(
|
yield stream_.async_shutdown(
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::loop,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&session::loop,
|
||||||
0,
|
shared_from_this(),
|
||||||
false)));
|
std::placeholders::_1,
|
||||||
|
0,
|
||||||
|
false)));
|
||||||
if(ec)
|
if(ec)
|
||||||
return fail(ec, "shutdown");
|
return fail(ec, "shutdown");
|
||||||
|
|
||||||
@ -373,13 +383,13 @@ class listener
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
listener(
|
listener(
|
||||||
boost::asio::io_service& ios,
|
boost::asio::io_context& ioc,
|
||||||
ssl::context& ctx,
|
ssl::context& ctx,
|
||||||
tcp::endpoint endpoint,
|
tcp::endpoint endpoint,
|
||||||
std::string const& doc_root)
|
std::string const& doc_root)
|
||||||
: ctx_(ctx)
|
: ctx_(ctx)
|
||||||
, acceptor_(ios)
|
, acceptor_(ioc)
|
||||||
, socket_(ios)
|
, socket_(ioc)
|
||||||
, doc_root_(doc_root)
|
, doc_root_(doc_root)
|
||||||
{
|
{
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
@ -402,7 +412,7 @@ public:
|
|||||||
|
|
||||||
// Start listening for connections
|
// Start listening for connections
|
||||||
acceptor_.listen(
|
acceptor_.listen(
|
||||||
boost::asio::socket_base::max_connections, ec);
|
boost::asio::socket_base::max_listen_connections, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
fail(ec, "listen");
|
fail(ec, "listen");
|
||||||
@ -464,13 +474,13 @@ int main(int argc, char* argv[])
|
|||||||
" http-server-stackless-ssl 0.0.0.0 8080 . 1\n";
|
" http-server-stackless-ssl 0.0.0.0 8080 . 1\n";
|
||||||
return EXIT_FAILURE;
|
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 port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||||
std::string const doc_root = argv[3];
|
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
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios{threads};
|
boost::asio::io_context ioc{threads};
|
||||||
|
|
||||||
// The SSL context is required, and holds certificates
|
// The SSL context is required, and holds certificates
|
||||||
ssl::context ctx{ssl::context::sslv23};
|
ssl::context ctx{ssl::context::sslv23};
|
||||||
@ -480,7 +490,7 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
// Create and launch a listening port
|
// Create and launch a listening port
|
||||||
std::make_shared<listener>(
|
std::make_shared<listener>(
|
||||||
ios,
|
ioc,
|
||||||
ctx,
|
ctx,
|
||||||
tcp::endpoint{address, port},
|
tcp::endpoint{address, port},
|
||||||
doc_root)->run();
|
doc_root)->run();
|
||||||
@ -490,11 +500,11 @@ int main(int argc, char* argv[])
|
|||||||
v.reserve(threads - 1);
|
v.reserve(threads - 1);
|
||||||
for(auto i = threads - 1; i > 0; --i)
|
for(auto i = threads - 1; i > 0; --i)
|
||||||
v.emplace_back(
|
v.emplace_back(
|
||||||
[&ios]
|
[&ioc]
|
||||||
{
|
{
|
||||||
ios.run();
|
ioc.run();
|
||||||
});
|
});
|
||||||
ios.run();
|
ioc.run();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <boost/beast/core.hpp>
|
#include <boost/beast/core.hpp>
|
||||||
#include <boost/beast/http.hpp>
|
#include <boost/beast/http.hpp>
|
||||||
#include <boost/beast/version.hpp>
|
#include <boost/beast/version.hpp>
|
||||||
|
#include <boost/asio/bind_executor.hpp>
|
||||||
#include <boost/asio/coroutine.hpp>
|
#include <boost/asio/coroutine.hpp>
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
#include <boost/asio/strand.hpp>
|
#include <boost/asio/strand.hpp>
|
||||||
@ -244,17 +245,20 @@ class session
|
|||||||
http::async_write(
|
http::async_write(
|
||||||
self_.socket_,
|
self_.socket_,
|
||||||
*sp,
|
*sp,
|
||||||
self_.strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::loop,
|
self_.strand_,
|
||||||
self_.shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&session::loop,
|
||||||
std::placeholders::_2,
|
self_.shared_from_this(),
|
||||||
! sp->keep_alive())));
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2,
|
||||||
|
! sp->keep_alive())));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
tcp::socket socket_;
|
tcp::socket socket_;
|
||||||
boost::asio::io_service::strand strand_;
|
boost::asio::strand<
|
||||||
|
boost::asio::io_context::executor_type> strand_;
|
||||||
boost::beast::flat_buffer buffer_;
|
boost::beast::flat_buffer buffer_;
|
||||||
std::string const& doc_root_;
|
std::string const& doc_root_;
|
||||||
http::request<http::string_body> req_;
|
http::request<http::string_body> req_;
|
||||||
@ -268,7 +272,7 @@ public:
|
|||||||
tcp::socket socket,
|
tcp::socket socket,
|
||||||
std::string const& doc_root)
|
std::string const& doc_root)
|
||||||
: socket_(std::move(socket))
|
: socket_(std::move(socket))
|
||||||
, strand_(socket_.get_io_service())
|
, strand_(socket_.get_executor())
|
||||||
, doc_root_(doc_root)
|
, doc_root_(doc_root)
|
||||||
, lambda_(*this)
|
, lambda_(*this)
|
||||||
{
|
{
|
||||||
@ -295,12 +299,14 @@ public:
|
|||||||
{
|
{
|
||||||
// Read a request
|
// Read a request
|
||||||
yield http::async_read(socket_, buffer_, req_,
|
yield http::async_read(socket_, buffer_, req_,
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::loop,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&session::loop,
|
||||||
std::placeholders::_2,
|
shared_from_this(),
|
||||||
false)));
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2,
|
||||||
|
false)));
|
||||||
if(ec == http::error::end_of_stream)
|
if(ec == http::error::end_of_stream)
|
||||||
{
|
{
|
||||||
// The remote host closed the connection
|
// The remote host closed the connection
|
||||||
@ -346,11 +352,11 @@ class listener
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
listener(
|
listener(
|
||||||
boost::asio::io_service& ios,
|
boost::asio::io_context& ioc,
|
||||||
tcp::endpoint endpoint,
|
tcp::endpoint endpoint,
|
||||||
std::string const& doc_root)
|
std::string const& doc_root)
|
||||||
: acceptor_(ios)
|
: acceptor_(ioc)
|
||||||
, socket_(ios)
|
, socket_(ioc)
|
||||||
, doc_root_(doc_root)
|
, doc_root_(doc_root)
|
||||||
{
|
{
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
@ -372,7 +378,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start listening for connections
|
// 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)
|
if(ec)
|
||||||
{
|
{
|
||||||
fail(ec, "listen");
|
fail(ec, "listen");
|
||||||
@ -433,17 +439,17 @@ int main(int argc, char* argv[])
|
|||||||
" http-server-stackless 0.0.0.0 8080 . 1\n";
|
" http-server-stackless 0.0.0.0 8080 . 1\n";
|
||||||
return EXIT_FAILURE;
|
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 port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||||
std::string const doc_root = argv[3];
|
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
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios{threads};
|
boost::asio::io_context ioc{threads};
|
||||||
|
|
||||||
// Create and launch a listening port
|
// Create and launch a listening port
|
||||||
std::make_shared<listener>(
|
std::make_shared<listener>(
|
||||||
ios,
|
ioc,
|
||||||
tcp::endpoint{address, port},
|
tcp::endpoint{address, port},
|
||||||
doc_root)->run();
|
doc_root)->run();
|
||||||
|
|
||||||
@ -452,11 +458,11 @@ int main(int argc, char* argv[])
|
|||||||
v.reserve(threads - 1);
|
v.reserve(threads - 1);
|
||||||
for(auto i = threads - 1; i > 0; --i)
|
for(auto i = threads - 1; i > 0; --i)
|
||||||
v.emplace_back(
|
v.emplace_back(
|
||||||
[&ios]
|
[&ioc]
|
||||||
{
|
{
|
||||||
ios.run();
|
ioc.run();
|
||||||
});
|
});
|
||||||
ios.run();
|
ioc.run();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -311,12 +311,12 @@ int main(int argc, char* argv[])
|
|||||||
" http-server-sync-ssl 0.0.0.0 8080 .\n";
|
" http-server-sync-ssl 0.0.0.0 8080 .\n";
|
||||||
return EXIT_FAILURE;
|
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 port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||||
std::string const doc_root = argv[3];
|
std::string const doc_root = argv[3];
|
||||||
|
|
||||||
// The io_service is required for all I/O
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios{1};
|
boost::asio::io_context ioc{1};
|
||||||
|
|
||||||
// The SSL context is required, and holds certificates
|
// The SSL context is required, and holds certificates
|
||||||
ssl::context ctx{ssl::context::sslv23};
|
ssl::context ctx{ssl::context::sslv23};
|
||||||
@ -325,11 +325,11 @@ int main(int argc, char* argv[])
|
|||||||
load_server_certificate(ctx);
|
load_server_certificate(ctx);
|
||||||
|
|
||||||
// The acceptor receives incoming connections
|
// The acceptor receives incoming connections
|
||||||
tcp::acceptor acceptor{ios, {address, port}};
|
tcp::acceptor acceptor{ioc, {address, port}};
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
// This will receive the new connection
|
// This will receive the new connection
|
||||||
tcp::socket socket{ios};
|
tcp::socket socket{ioc};
|
||||||
|
|
||||||
// Block until we get a connection
|
// Block until we get a connection
|
||||||
acceptor.accept(socket);
|
acceptor.accept(socket);
|
||||||
|
@ -298,19 +298,19 @@ int main(int argc, char* argv[])
|
|||||||
" http-server-sync 0.0.0.0 8080 .\n";
|
" http-server-sync 0.0.0.0 8080 .\n";
|
||||||
return EXIT_FAILURE;
|
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 port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||||
std::string const doc_root = argv[3];
|
std::string const doc_root = argv[3];
|
||||||
|
|
||||||
// The io_service is required for all I/O
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios{1};
|
boost::asio::io_context ioc{1};
|
||||||
|
|
||||||
// The acceptor receives incoming connections
|
// The acceptor receives incoming connections
|
||||||
tcp::acceptor acceptor{ios, {address, port}};
|
tcp::acceptor acceptor{ioc, {address, port}};
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
// This will receive the new connection
|
// This will receive the new connection
|
||||||
tcp::socket socket{ios};
|
tcp::socket socket{ioc};
|
||||||
|
|
||||||
// Block until we get a connection
|
// Block until we get a connection
|
||||||
acceptor.accept(socket);
|
acceptor.accept(socket);
|
||||||
|
@ -50,11 +50,11 @@ class session : public std::enable_shared_from_this<session>
|
|||||||
std::string text_;
|
std::string text_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Resolver and socket require an io_service
|
// Resolver and socket require an io_context
|
||||||
explicit
|
explicit
|
||||||
session(boost::asio::io_service& ios, ssl::context& ctx)
|
session(boost::asio::io_context& ioc, ssl::context& ctx)
|
||||||
: resolver_(ios)
|
: resolver_(ioc)
|
||||||
, ws_(ios, ctx)
|
, ws_(ioc, ctx)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +70,9 @@ public:
|
|||||||
text_ = text;
|
text_ = text;
|
||||||
|
|
||||||
// Look up the domain name
|
// Look up the domain name
|
||||||
resolver_.async_resolve({host, port},
|
resolver_.async_resolve(
|
||||||
|
host,
|
||||||
|
port,
|
||||||
std::bind(
|
std::bind(
|
||||||
&session::on_resolve,
|
&session::on_resolve,
|
||||||
shared_from_this(),
|
shared_from_this(),
|
||||||
@ -81,7 +83,7 @@ public:
|
|||||||
void
|
void
|
||||||
on_resolve(
|
on_resolve(
|
||||||
boost::system::error_code ec,
|
boost::system::error_code ec,
|
||||||
tcp::resolver::iterator result)
|
tcp::resolver::results_type results)
|
||||||
{
|
{
|
||||||
if(ec)
|
if(ec)
|
||||||
return fail(ec, "resolve");
|
return fail(ec, "resolve");
|
||||||
@ -89,7 +91,8 @@ public:
|
|||||||
// Make the connection on the IP address we get from a lookup
|
// Make the connection on the IP address we get from a lookup
|
||||||
boost::asio::async_connect(
|
boost::asio::async_connect(
|
||||||
ws_.next_layer().next_layer(),
|
ws_.next_layer().next_layer(),
|
||||||
result,
|
results.begin(),
|
||||||
|
results.end(),
|
||||||
std::bind(
|
std::bind(
|
||||||
&session::on_connect,
|
&session::on_connect,
|
||||||
shared_from_this(),
|
shared_from_this(),
|
||||||
@ -209,8 +212,8 @@ int main(int argc, char** argv)
|
|||||||
auto const port = argv[2];
|
auto const port = argv[2];
|
||||||
auto const text = argv[3];
|
auto const text = argv[3];
|
||||||
|
|
||||||
// The io_service is required for all I/O
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios;
|
boost::asio::io_context ioc;
|
||||||
|
|
||||||
// The SSL context is required, and holds certificates
|
// The SSL context is required, and holds certificates
|
||||||
ssl::context ctx{ssl::context::sslv23_client};
|
ssl::context ctx{ssl::context::sslv23_client};
|
||||||
@ -219,11 +222,11 @@ int main(int argc, char** argv)
|
|||||||
load_root_certificates(ctx);
|
load_root_certificates(ctx);
|
||||||
|
|
||||||
// Launch the asynchronous operation
|
// 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
|
// Run the I/O service. The call will return when
|
||||||
// the get operation is complete.
|
// the get operation is complete.
|
||||||
ios.run();
|
ioc.run();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -45,11 +45,11 @@ class session : public std::enable_shared_from_this<session>
|
|||||||
std::string text_;
|
std::string text_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Resolver and socket require an io_service
|
// Resolver and socket require an io_context
|
||||||
explicit
|
explicit
|
||||||
session(boost::asio::io_service& ios)
|
session(boost::asio::io_context& ioc)
|
||||||
: resolver_(ios)
|
: resolver_(ioc)
|
||||||
, ws_(ios)
|
, ws_(ioc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +65,9 @@ public:
|
|||||||
text_ = text;
|
text_ = text;
|
||||||
|
|
||||||
// Look up the domain name
|
// Look up the domain name
|
||||||
resolver_.async_resolve({host, port},
|
resolver_.async_resolve(
|
||||||
|
host,
|
||||||
|
port,
|
||||||
std::bind(
|
std::bind(
|
||||||
&session::on_resolve,
|
&session::on_resolve,
|
||||||
shared_from_this(),
|
shared_from_this(),
|
||||||
@ -76,7 +78,7 @@ public:
|
|||||||
void
|
void
|
||||||
on_resolve(
|
on_resolve(
|
||||||
boost::system::error_code ec,
|
boost::system::error_code ec,
|
||||||
tcp::resolver::iterator result)
|
tcp::resolver::results_type results)
|
||||||
{
|
{
|
||||||
if(ec)
|
if(ec)
|
||||||
return fail(ec, "resolve");
|
return fail(ec, "resolve");
|
||||||
@ -84,7 +86,8 @@ public:
|
|||||||
// Make the connection on the IP address we get from a lookup
|
// Make the connection on the IP address we get from a lookup
|
||||||
boost::asio::async_connect(
|
boost::asio::async_connect(
|
||||||
ws_.next_layer(),
|
ws_.next_layer(),
|
||||||
result,
|
results.begin(),
|
||||||
|
results.end(),
|
||||||
std::bind(
|
std::bind(
|
||||||
&session::on_connect,
|
&session::on_connect,
|
||||||
shared_from_this(),
|
shared_from_this(),
|
||||||
@ -189,15 +192,15 @@ int main(int argc, char** argv)
|
|||||||
auto const port = argv[2];
|
auto const port = argv[2];
|
||||||
auto const text = argv[3];
|
auto const text = argv[3];
|
||||||
|
|
||||||
// The io_service is required for all I/O
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios;
|
boost::asio::io_context ioc;
|
||||||
|
|
||||||
// Launch the asynchronous operation
|
// 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
|
// Run the I/O service. The call will return when
|
||||||
// the get operation is complete.
|
// the get operation is complete.
|
||||||
ios.run();
|
ioc.run();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -46,23 +46,23 @@ do_session(
|
|||||||
std::string const& host,
|
std::string const& host,
|
||||||
std::string const& port,
|
std::string const& port,
|
||||||
std::string const& text,
|
std::string const& text,
|
||||||
boost::asio::io_service& ios,
|
boost::asio::io_context& ioc,
|
||||||
ssl::context& ctx,
|
ssl::context& ctx,
|
||||||
boost::asio::yield_context yield)
|
boost::asio::yield_context yield)
|
||||||
{
|
{
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
|
|
||||||
// These objects perform our I/O
|
// These objects perform our I/O
|
||||||
tcp::resolver resolver{ios};
|
tcp::resolver resolver{ioc};
|
||||||
websocket::stream<ssl::stream<tcp::socket>> ws{ios, ctx};
|
websocket::stream<ssl::stream<tcp::socket>> ws{ioc, ctx};
|
||||||
|
|
||||||
// Look up the domain name
|
// 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)
|
if(ec)
|
||||||
return fail(ec, "resolve");
|
return fail(ec, "resolve");
|
||||||
|
|
||||||
// Make the connection on the IP address we get from a lookup
|
// 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)
|
if(ec)
|
||||||
return fail(ec, "connect");
|
return fail(ec, "connect");
|
||||||
|
|
||||||
@ -117,8 +117,8 @@ int main(int argc, char** argv)
|
|||||||
auto const port = argv[2];
|
auto const port = argv[2];
|
||||||
auto const text = argv[3];
|
auto const text = argv[3];
|
||||||
|
|
||||||
// The io_service is required for all I/O
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios;
|
boost::asio::io_context ioc;
|
||||||
|
|
||||||
// The SSL context is required, and holds certificates
|
// The SSL context is required, and holds certificates
|
||||||
ssl::context ctx{ssl::context::sslv23_client};
|
ssl::context ctx{ssl::context::sslv23_client};
|
||||||
@ -127,18 +127,18 @@ int main(int argc, char** argv)
|
|||||||
load_root_certificates(ctx);
|
load_root_certificates(ctx);
|
||||||
|
|
||||||
// Launch the asynchronous operation
|
// Launch the asynchronous operation
|
||||||
boost::asio::spawn(ios, std::bind(
|
boost::asio::spawn(ioc, std::bind(
|
||||||
&do_session,
|
&do_session,
|
||||||
std::string(host),
|
std::string(host),
|
||||||
std::string(port),
|
std::string(port),
|
||||||
std::string(text),
|
std::string(text),
|
||||||
std::ref(ios),
|
std::ref(ioc),
|
||||||
std::ref(ctx),
|
std::ref(ctx),
|
||||||
std::placeholders::_1));
|
std::placeholders::_1));
|
||||||
|
|
||||||
// Run the I/O service. The call will return when
|
// Run the I/O service. The call will return when
|
||||||
// the get operation is complete.
|
// the get operation is complete.
|
||||||
ios.run();
|
ioc.run();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -41,22 +41,22 @@ do_session(
|
|||||||
std::string const& host,
|
std::string const& host,
|
||||||
std::string const& port,
|
std::string const& port,
|
||||||
std::string const& text,
|
std::string const& text,
|
||||||
boost::asio::io_service& ios,
|
boost::asio::io_context& ioc,
|
||||||
boost::asio::yield_context yield)
|
boost::asio::yield_context yield)
|
||||||
{
|
{
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
|
|
||||||
// These objects perform our I/O
|
// These objects perform our I/O
|
||||||
tcp::resolver resolver{ios};
|
tcp::resolver resolver{ioc};
|
||||||
websocket::stream<tcp::socket> ws{ios};
|
websocket::stream<tcp::socket> ws{ioc};
|
||||||
|
|
||||||
// Look up the domain name
|
// 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)
|
if(ec)
|
||||||
return fail(ec, "resolve");
|
return fail(ec, "resolve");
|
||||||
|
|
||||||
// Make the connection on the IP address we get from a lookup
|
// 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)
|
if(ec)
|
||||||
return fail(ec, "connect");
|
return fail(ec, "connect");
|
||||||
|
|
||||||
@ -106,21 +106,21 @@ int main(int argc, char** argv)
|
|||||||
auto const port = argv[2];
|
auto const port = argv[2];
|
||||||
auto const text = argv[3];
|
auto const text = argv[3];
|
||||||
|
|
||||||
// The io_service is required for all I/O
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios;
|
boost::asio::io_context ioc;
|
||||||
|
|
||||||
// Launch the asynchronous operation
|
// Launch the asynchronous operation
|
||||||
boost::asio::spawn(ios, std::bind(
|
boost::asio::spawn(ioc, std::bind(
|
||||||
&do_session,
|
&do_session,
|
||||||
std::string(host),
|
std::string(host),
|
||||||
std::string(port),
|
std::string(port),
|
||||||
std::string(text),
|
std::string(text),
|
||||||
std::ref(ios),
|
std::ref(ioc),
|
||||||
std::placeholders::_1));
|
std::placeholders::_1));
|
||||||
|
|
||||||
// Run the I/O service. The call will return when
|
// Run the I/O service. The call will return when
|
||||||
// the get operation is complete.
|
// the get operation is complete.
|
||||||
ios.run();
|
ioc.run();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -47,8 +47,8 @@ int main(int argc, char** argv)
|
|||||||
auto const port = argv[2];
|
auto const port = argv[2];
|
||||||
auto const text = argv[3];
|
auto const text = argv[3];
|
||||||
|
|
||||||
// The io_service is required for all I/O
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios;
|
boost::asio::io_context ioc;
|
||||||
|
|
||||||
// The SSL context is required, and holds certificates
|
// The SSL context is required, and holds certificates
|
||||||
ssl::context ctx{ssl::context::sslv23_client};
|
ssl::context ctx{ssl::context::sslv23_client};
|
||||||
@ -57,14 +57,14 @@ int main(int argc, char** argv)
|
|||||||
load_root_certificates(ctx);
|
load_root_certificates(ctx);
|
||||||
|
|
||||||
// These objects perform our I/O
|
// These objects perform our I/O
|
||||||
tcp::resolver resolver{ios};
|
tcp::resolver resolver{ioc};
|
||||||
websocket::stream<ssl::stream<tcp::socket>> ws{ios, ctx};
|
websocket::stream<ssl::stream<tcp::socket>> ws{ioc, ctx};
|
||||||
|
|
||||||
// Look up the domain name
|
// 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
|
// 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
|
// Perform the SSL handshake
|
||||||
ws.next_layer().handshake(ssl::stream_base::client);
|
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 port = argv[2];
|
||||||
auto const text = argv[3];
|
auto const text = argv[3];
|
||||||
|
|
||||||
// The io_service is required for all I/O
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios;
|
boost::asio::io_context ioc;
|
||||||
|
|
||||||
// These objects perform our I/O
|
// These objects perform our I/O
|
||||||
tcp::resolver resolver{ios};
|
tcp::resolver resolver{ioc};
|
||||||
websocket::stream<tcp::socket> ws{ios};
|
websocket::stream<tcp::socket> ws{ioc};
|
||||||
|
|
||||||
// Look up the domain name
|
// 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
|
// 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
|
// Perform the websocket handshake
|
||||||
ws.handshake(host, "/");
|
ws.handshake(host, "/");
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include <boost/beast/core.hpp>
|
#include <boost/beast/core.hpp>
|
||||||
#include <boost/beast/websocket.hpp>
|
#include <boost/beast/websocket.hpp>
|
||||||
#include <boost/beast/websocket/ssl.hpp>
|
#include <boost/beast/websocket/ssl.hpp>
|
||||||
|
#include <boost/asio/bind_executor.hpp>
|
||||||
#include <boost/asio/strand.hpp>
|
#include <boost/asio/strand.hpp>
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
#include <boost/asio/ssl/stream.hpp>
|
#include <boost/asio/ssl/stream.hpp>
|
||||||
@ -48,7 +49,8 @@ class session : public std::enable_shared_from_this<session>
|
|||||||
{
|
{
|
||||||
tcp::socket socket_;
|
tcp::socket socket_;
|
||||||
websocket::stream<ssl::stream<tcp::socket&>> ws_;
|
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_;
|
boost::beast::multi_buffer buffer_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -56,7 +58,7 @@ public:
|
|||||||
session(tcp::socket socket, ssl::context& ctx)
|
session(tcp::socket socket, ssl::context& ctx)
|
||||||
: socket_(std::move(socket))
|
: socket_(std::move(socket))
|
||||||
, ws_(socket_, ctx)
|
, ws_(socket_, ctx)
|
||||||
, strand_(ws_.get_io_service())
|
, strand_(ws_.get_executor())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,10 +69,12 @@ public:
|
|||||||
// Perform the SSL handshake
|
// Perform the SSL handshake
|
||||||
ws_.next_layer().async_handshake(
|
ws_.next_layer().async_handshake(
|
||||||
ssl::stream_base::server,
|
ssl::stream_base::server,
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::on_handshake,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1)));
|
&session::on_handshake,
|
||||||
|
shared_from_this(),
|
||||||
|
std::placeholders::_1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -81,10 +85,12 @@ public:
|
|||||||
|
|
||||||
// Accept the websocket handshake
|
// Accept the websocket handshake
|
||||||
ws_.async_accept(
|
ws_.async_accept(
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::on_accept,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1)));
|
&session::on_accept,
|
||||||
|
shared_from_this(),
|
||||||
|
std::placeholders::_1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -103,11 +109,13 @@ public:
|
|||||||
// Read a message into our buffer
|
// Read a message into our buffer
|
||||||
ws_.async_read(
|
ws_.async_read(
|
||||||
buffer_,
|
buffer_,
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::on_read,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&session::on_read,
|
||||||
std::placeholders::_2)));
|
shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -128,11 +136,13 @@ public:
|
|||||||
ws_.text(ws_.got_text());
|
ws_.text(ws_.got_text());
|
||||||
ws_.async_write(
|
ws_.async_write(
|
||||||
buffer_.data(),
|
buffer_.data(),
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::on_write,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&session::on_write,
|
||||||
std::placeholders::_2)));
|
shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -164,12 +174,12 @@ class listener : public std::enable_shared_from_this<listener>
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
listener(
|
listener(
|
||||||
boost::asio::io_service& ios,
|
boost::asio::io_context& ioc,
|
||||||
ssl::context& ctx,
|
ssl::context& ctx,
|
||||||
tcp::endpoint endpoint)
|
tcp::endpoint endpoint)
|
||||||
: ctx_(ctx)
|
: ctx_(ctx)
|
||||||
, acceptor_(ios)
|
, acceptor_(ioc)
|
||||||
, socket_(ios)
|
, socket_(ioc)
|
||||||
{
|
{
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
|
|
||||||
@ -191,7 +201,7 @@ public:
|
|||||||
|
|
||||||
// Start listening for connections
|
// Start listening for connections
|
||||||
acceptor_.listen(
|
acceptor_.listen(
|
||||||
boost::asio::socket_base::max_connections, ec);
|
boost::asio::socket_base::max_listen_connections, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
fail(ec, "listen");
|
fail(ec, "listen");
|
||||||
@ -250,12 +260,12 @@ int main(int argc, char* argv[])
|
|||||||
" websocket-server-async-ssl 0.0.0.0 8080 1\n";
|
" websocket-server-async-ssl 0.0.0.0 8080 1\n";
|
||||||
return EXIT_FAILURE;
|
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 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
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios{threads};
|
boost::asio::io_context ioc{threads};
|
||||||
|
|
||||||
// The SSL context is required, and holds certificates
|
// The SSL context is required, and holds certificates
|
||||||
ssl::context ctx{ssl::context::sslv23};
|
ssl::context ctx{ssl::context::sslv23};
|
||||||
@ -264,18 +274,18 @@ int main(int argc, char* argv[])
|
|||||||
load_server_certificate(ctx);
|
load_server_certificate(ctx);
|
||||||
|
|
||||||
// Create and launch a listening port
|
// 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
|
// Run the I/O service on the requested number of threads
|
||||||
std::vector<std::thread> v;
|
std::vector<std::thread> v;
|
||||||
v.reserve(threads - 1);
|
v.reserve(threads - 1);
|
||||||
for(auto i = threads - 1; i > 0; --i)
|
for(auto i = threads - 1; i > 0; --i)
|
||||||
v.emplace_back(
|
v.emplace_back(
|
||||||
[&ios]
|
[&ioc]
|
||||||
{
|
{
|
||||||
ios.run();
|
ioc.run();
|
||||||
});
|
});
|
||||||
ios.run();
|
ioc.run();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include <boost/beast/core.hpp>
|
#include <boost/beast/core.hpp>
|
||||||
#include <boost/beast/websocket.hpp>
|
#include <boost/beast/websocket.hpp>
|
||||||
|
#include <boost/asio/bind_executor.hpp>
|
||||||
#include <boost/asio/strand.hpp>
|
#include <boost/asio/strand.hpp>
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -42,7 +43,8 @@ fail(boost::system::error_code ec, char const* what)
|
|||||||
class session : public std::enable_shared_from_this<session>
|
class session : public std::enable_shared_from_this<session>
|
||||||
{
|
{
|
||||||
websocket::stream<tcp::socket> ws_;
|
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_;
|
boost::beast::multi_buffer buffer_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -50,7 +52,7 @@ public:
|
|||||||
explicit
|
explicit
|
||||||
session(tcp::socket socket)
|
session(tcp::socket socket)
|
||||||
: ws_(std::move(socket))
|
: ws_(std::move(socket))
|
||||||
, strand_(ws_.get_io_service())
|
, strand_(ws_.get_executor())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,10 +62,12 @@ public:
|
|||||||
{
|
{
|
||||||
// Accept the websocket handshake
|
// Accept the websocket handshake
|
||||||
ws_.async_accept(
|
ws_.async_accept(
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::on_accept,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1)));
|
&session::on_accept,
|
||||||
|
shared_from_this(),
|
||||||
|
std::placeholders::_1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -82,11 +86,13 @@ public:
|
|||||||
// Read a message into our buffer
|
// Read a message into our buffer
|
||||||
ws_.async_read(
|
ws_.async_read(
|
||||||
buffer_,
|
buffer_,
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::on_read,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&session::on_read,
|
||||||
std::placeholders::_2)));
|
shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -107,11 +113,13 @@ public:
|
|||||||
ws_.text(ws_.got_text());
|
ws_.text(ws_.got_text());
|
||||||
ws_.async_write(
|
ws_.async_write(
|
||||||
buffer_.data(),
|
buffer_.data(),
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::on_write,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&session::on_write,
|
||||||
std::placeholders::_2)));
|
shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -142,10 +150,10 @@ class listener : public std::enable_shared_from_this<listener>
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
listener(
|
listener(
|
||||||
boost::asio::io_service& ios,
|
boost::asio::io_context& ioc,
|
||||||
tcp::endpoint endpoint)
|
tcp::endpoint endpoint)
|
||||||
: acceptor_(ios)
|
: acceptor_(ioc)
|
||||||
, socket_(ios)
|
, socket_(ioc)
|
||||||
{
|
{
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
|
|
||||||
@ -167,7 +175,7 @@ public:
|
|||||||
|
|
||||||
// Start listening for connections
|
// Start listening for connections
|
||||||
acceptor_.listen(
|
acceptor_.listen(
|
||||||
boost::asio::socket_base::max_connections, ec);
|
boost::asio::socket_base::max_listen_connections, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
fail(ec, "listen");
|
fail(ec, "listen");
|
||||||
@ -226,26 +234,26 @@ int main(int argc, char* argv[])
|
|||||||
" websocket-server-async 0.0.0.0 8080 1\n";
|
" websocket-server-async 0.0.0.0 8080 1\n";
|
||||||
return EXIT_FAILURE;
|
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 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
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios{threads};
|
boost::asio::io_context ioc{threads};
|
||||||
|
|
||||||
// Create and launch a listening port
|
// 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
|
// Run the I/O service on the requested number of threads
|
||||||
std::vector<std::thread> v;
|
std::vector<std::thread> v;
|
||||||
v.reserve(threads - 1);
|
v.reserve(threads - 1);
|
||||||
for(auto i = threads - 1; i > 0; --i)
|
for(auto i = threads - 1; i > 0; --i)
|
||||||
v.emplace_back(
|
v.emplace_back(
|
||||||
[&ios]
|
[&ioc]
|
||||||
{
|
{
|
||||||
ios.run();
|
ioc.run();
|
||||||
});
|
});
|
||||||
ios.run();
|
ioc.run();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ do_session(
|
|||||||
// Accepts incoming connections and launches the sessions
|
// Accepts incoming connections and launches the sessions
|
||||||
void
|
void
|
||||||
do_listen(
|
do_listen(
|
||||||
boost::asio::io_service& ios,
|
boost::asio::io_context& ioc,
|
||||||
ssl::context& ctx,
|
ssl::context& ctx,
|
||||||
tcp::endpoint endpoint,
|
tcp::endpoint endpoint,
|
||||||
boost::asio::yield_context yield)
|
boost::asio::yield_context yield)
|
||||||
@ -101,7 +101,7 @@ do_listen(
|
|||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
|
|
||||||
// Open the acceptor
|
// Open the acceptor
|
||||||
tcp::acceptor acceptor(ios);
|
tcp::acceptor acceptor(ioc);
|
||||||
acceptor.open(endpoint.protocol(), ec);
|
acceptor.open(endpoint.protocol(), ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return fail(ec, "open");
|
return fail(ec, "open");
|
||||||
@ -112,19 +112,19 @@ do_listen(
|
|||||||
return fail(ec, "bind");
|
return fail(ec, "bind");
|
||||||
|
|
||||||
// Start listening for connections
|
// 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)
|
if(ec)
|
||||||
return fail(ec, "listen");
|
return fail(ec, "listen");
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
tcp::socket socket(ios);
|
tcp::socket socket(ioc);
|
||||||
acceptor.async_accept(socket, yield[ec]);
|
acceptor.async_accept(socket, yield[ec]);
|
||||||
if(ec)
|
if(ec)
|
||||||
fail(ec, "accept");
|
fail(ec, "accept");
|
||||||
else
|
else
|
||||||
boost::asio::spawn(
|
boost::asio::spawn(
|
||||||
acceptor.get_io_service(),
|
acceptor.get_executor().context(),
|
||||||
std::bind(
|
std::bind(
|
||||||
&do_session,
|
&do_session,
|
||||||
std::move(socket),
|
std::move(socket),
|
||||||
@ -144,12 +144,12 @@ int main(int argc, char* argv[])
|
|||||||
" websocket-server-coro-ssl 0.0.0.0 8080 1\n";
|
" websocket-server-coro-ssl 0.0.0.0 8080 1\n";
|
||||||
return EXIT_FAILURE;
|
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 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
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios{threads};
|
boost::asio::io_context ioc{threads};
|
||||||
|
|
||||||
// The SSL context is required, and holds certificates
|
// The SSL context is required, and holds certificates
|
||||||
ssl::context ctx{ssl::context::sslv23};
|
ssl::context ctx{ssl::context::sslv23};
|
||||||
@ -158,10 +158,10 @@ int main(int argc, char* argv[])
|
|||||||
load_server_certificate(ctx);
|
load_server_certificate(ctx);
|
||||||
|
|
||||||
// Spawn a listening port
|
// Spawn a listening port
|
||||||
boost::asio::spawn(ios,
|
boost::asio::spawn(ioc,
|
||||||
std::bind(
|
std::bind(
|
||||||
&do_listen,
|
&do_listen,
|
||||||
std::ref(ios),
|
std::ref(ioc),
|
||||||
std::ref(ctx),
|
std::ref(ctx),
|
||||||
tcp::endpoint{address, port},
|
tcp::endpoint{address, port},
|
||||||
std::placeholders::_1));
|
std::placeholders::_1));
|
||||||
@ -171,11 +171,11 @@ int main(int argc, char* argv[])
|
|||||||
v.reserve(threads - 1);
|
v.reserve(threads - 1);
|
||||||
for(auto i = threads - 1; i > 0; --i)
|
for(auto i = threads - 1; i > 0; --i)
|
||||||
v.emplace_back(
|
v.emplace_back(
|
||||||
[&ios]
|
[&ioc]
|
||||||
{
|
{
|
||||||
ios.run();
|
ioc.run();
|
||||||
});
|
});
|
||||||
ios.run();
|
ioc.run();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -80,14 +80,14 @@ do_session(tcp::socket& socket, boost::asio::yield_context yield)
|
|||||||
// Accepts incoming connections and launches the sessions
|
// Accepts incoming connections and launches the sessions
|
||||||
void
|
void
|
||||||
do_listen(
|
do_listen(
|
||||||
boost::asio::io_service& ios,
|
boost::asio::io_context& ioc,
|
||||||
tcp::endpoint endpoint,
|
tcp::endpoint endpoint,
|
||||||
boost::asio::yield_context yield)
|
boost::asio::yield_context yield)
|
||||||
{
|
{
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
|
|
||||||
// Open the acceptor
|
// Open the acceptor
|
||||||
tcp::acceptor acceptor(ios);
|
tcp::acceptor acceptor(ioc);
|
||||||
acceptor.open(endpoint.protocol(), ec);
|
acceptor.open(endpoint.protocol(), ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return fail(ec, "open");
|
return fail(ec, "open");
|
||||||
@ -98,19 +98,19 @@ do_listen(
|
|||||||
return fail(ec, "bind");
|
return fail(ec, "bind");
|
||||||
|
|
||||||
// Start listening for connections
|
// 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)
|
if(ec)
|
||||||
return fail(ec, "listen");
|
return fail(ec, "listen");
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
tcp::socket socket(ios);
|
tcp::socket socket(ioc);
|
||||||
acceptor.async_accept(socket, yield[ec]);
|
acceptor.async_accept(socket, yield[ec]);
|
||||||
if(ec)
|
if(ec)
|
||||||
fail(ec, "accept");
|
fail(ec, "accept");
|
||||||
else
|
else
|
||||||
boost::asio::spawn(
|
boost::asio::spawn(
|
||||||
acceptor.get_io_service(),
|
acceptor.get_executor().context(),
|
||||||
std::bind(
|
std::bind(
|
||||||
&do_session,
|
&do_session,
|
||||||
std::move(socket),
|
std::move(socket),
|
||||||
@ -129,18 +129,18 @@ int main(int argc, char* argv[])
|
|||||||
" websocket-server-coro 0.0.0.0 8080 1\n";
|
" websocket-server-coro 0.0.0.0 8080 1\n";
|
||||||
return EXIT_FAILURE;
|
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 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
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios{threads};
|
boost::asio::io_context ioc{threads};
|
||||||
|
|
||||||
// Spawn a listening port
|
// Spawn a listening port
|
||||||
boost::asio::spawn(ios,
|
boost::asio::spawn(ioc,
|
||||||
std::bind(
|
std::bind(
|
||||||
&do_listen,
|
&do_listen,
|
||||||
std::ref(ios),
|
std::ref(ioc),
|
||||||
tcp::endpoint{address, port},
|
tcp::endpoint{address, port},
|
||||||
std::placeholders::_1));
|
std::placeholders::_1));
|
||||||
|
|
||||||
@ -149,11 +149,11 @@ int main(int argc, char* argv[])
|
|||||||
v.reserve(threads - 1);
|
v.reserve(threads - 1);
|
||||||
for(auto i = threads - 1; i > 0; --i)
|
for(auto i = threads - 1; i > 0; --i)
|
||||||
v.emplace_back(
|
v.emplace_back(
|
||||||
[&ios]
|
[&ioc]
|
||||||
{
|
{
|
||||||
ios.run();
|
ioc.run();
|
||||||
});
|
});
|
||||||
ios.run();
|
ioc.run();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <boost/beast/http.hpp>
|
#include <boost/beast/http.hpp>
|
||||||
#include <boost/beast/version.hpp>
|
#include <boost/beast/version.hpp>
|
||||||
#include <boost/beast/websocket.hpp>
|
#include <boost/beast/websocket.hpp>
|
||||||
|
#include <boost/asio/bind_executor.hpp>
|
||||||
#include <boost/asio/spawn.hpp>
|
#include <boost/asio/spawn.hpp>
|
||||||
#include <boost/asio/strand.hpp>
|
#include <boost/asio/strand.hpp>
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
@ -113,14 +114,14 @@ do_sync_session(tcp::socket& socket)
|
|||||||
|
|
||||||
void
|
void
|
||||||
do_sync_listen(
|
do_sync_listen(
|
||||||
boost::asio::io_service& ios,
|
boost::asio::io_context& ioc,
|
||||||
tcp::endpoint endpoint)
|
tcp::endpoint endpoint)
|
||||||
{
|
{
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
tcp::acceptor acceptor{ios, endpoint};
|
tcp::acceptor acceptor{ioc, endpoint};
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
tcp::socket socket{ios};
|
tcp::socket socket{ioc};
|
||||||
|
|
||||||
acceptor.accept(socket, ec);
|
acceptor.accept(socket, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
@ -138,7 +139,8 @@ do_sync_listen(
|
|||||||
class async_session : public std::enable_shared_from_this<async_session>
|
class async_session : public std::enable_shared_from_this<async_session>
|
||||||
{
|
{
|
||||||
websocket::stream<tcp::socket> ws_;
|
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_;
|
boost::beast::multi_buffer buffer_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -146,7 +148,7 @@ public:
|
|||||||
explicit
|
explicit
|
||||||
async_session(tcp::socket socket)
|
async_session(tcp::socket socket)
|
||||||
: ws_(std::move(socket))
|
: ws_(std::move(socket))
|
||||||
, strand_(ws_.get_io_service())
|
, strand_(ws_.get_executor())
|
||||||
{
|
{
|
||||||
setup_stream(ws_);
|
setup_stream(ws_);
|
||||||
}
|
}
|
||||||
@ -162,10 +164,12 @@ public:
|
|||||||
res.set(http::field::server,
|
res.set(http::field::server,
|
||||||
"Boost.Beast.async/" + std::to_string(BOOST_BEAST_VERSION));
|
"Boost.Beast.async/" + std::to_string(BOOST_BEAST_VERSION));
|
||||||
},
|
},
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&async_session::on_accept,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1)));
|
&async_session::on_accept,
|
||||||
|
shared_from_this(),
|
||||||
|
std::placeholders::_1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -184,11 +188,13 @@ public:
|
|||||||
// Read a message into our buffer
|
// Read a message into our buffer
|
||||||
ws_.async_read(
|
ws_.async_read(
|
||||||
buffer_,
|
buffer_,
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&async_session::on_read,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&async_session::on_read,
|
||||||
std::placeholders::_2)));
|
shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -209,11 +215,13 @@ public:
|
|||||||
ws_.text(ws_.got_text());
|
ws_.text(ws_.got_text());
|
||||||
ws_.async_write(
|
ws_.async_write(
|
||||||
buffer_.data(),
|
buffer_.data(),
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&async_session::on_write,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&async_session::on_write,
|
||||||
std::placeholders::_2)));
|
shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -237,17 +245,18 @@ public:
|
|||||||
// Accepts incoming connections and launches the sessions
|
// Accepts incoming connections and launches the sessions
|
||||||
class async_listener : public std::enable_shared_from_this<async_listener>
|
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::acceptor acceptor_;
|
||||||
tcp::socket socket_;
|
tcp::socket socket_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
async_listener(
|
async_listener(
|
||||||
boost::asio::io_service& ios,
|
boost::asio::io_context& ioc,
|
||||||
tcp::endpoint endpoint)
|
tcp::endpoint endpoint)
|
||||||
: strand_(ios)
|
: strand_(ioc.get_executor())
|
||||||
, acceptor_(ios)
|
, acceptor_(ioc)
|
||||||
, socket_(ios)
|
, socket_(ioc)
|
||||||
{
|
{
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
|
|
||||||
@ -269,7 +278,7 @@ public:
|
|||||||
|
|
||||||
// Start listening for connections
|
// Start listening for connections
|
||||||
acceptor_.listen(
|
acceptor_.listen(
|
||||||
boost::asio::socket_base::max_connections, ec);
|
boost::asio::socket_base::max_listen_connections, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
fail(ec, "listen");
|
fail(ec, "listen");
|
||||||
@ -291,10 +300,12 @@ public:
|
|||||||
{
|
{
|
||||||
acceptor_.async_accept(
|
acceptor_.async_accept(
|
||||||
socket_,
|
socket_,
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&async_listener::on_accept,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1)));
|
&async_listener::on_accept,
|
||||||
|
shared_from_this(),
|
||||||
|
std::placeholders::_1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -354,13 +365,13 @@ do_coro_session(tcp::socket& socket, boost::asio::yield_context yield)
|
|||||||
|
|
||||||
void
|
void
|
||||||
do_coro_listen(
|
do_coro_listen(
|
||||||
boost::asio::io_service& ios,
|
boost::asio::io_context& ioc,
|
||||||
tcp::endpoint endpoint,
|
tcp::endpoint endpoint,
|
||||||
boost::asio::yield_context yield)
|
boost::asio::yield_context yield)
|
||||||
{
|
{
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
|
|
||||||
tcp::acceptor acceptor(ios);
|
tcp::acceptor acceptor(ioc);
|
||||||
acceptor.open(endpoint.protocol(), ec);
|
acceptor.open(endpoint.protocol(), ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return fail(ec, "open");
|
return fail(ec, "open");
|
||||||
@ -369,13 +380,13 @@ do_coro_listen(
|
|||||||
if(ec)
|
if(ec)
|
||||||
return fail(ec, "bind");
|
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)
|
if(ec)
|
||||||
return fail(ec, "listen");
|
return fail(ec, "listen");
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
tcp::socket socket(ios);
|
tcp::socket socket(ioc);
|
||||||
|
|
||||||
acceptor.async_accept(socket, yield[ec]);
|
acceptor.async_accept(socket, yield[ec]);
|
||||||
if(ec)
|
if(ec)
|
||||||
@ -385,7 +396,7 @@ do_coro_listen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
boost::asio::spawn(
|
boost::asio::spawn(
|
||||||
acceptor.get_io_service(),
|
acceptor.get_executor().context(),
|
||||||
std::bind(
|
std::bind(
|
||||||
&do_coro_session,
|
&do_coro_session,
|
||||||
std::move(socket),
|
std::move(socket),
|
||||||
@ -410,17 +421,17 @@ int main(int argc, char* argv[])
|
|||||||
" starting-port+2 for coroutine.\n";
|
" starting-port+2 for coroutine.\n";
|
||||||
return EXIT_FAILURE;
|
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 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
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios{threads};
|
boost::asio::io_context ioc{threads};
|
||||||
|
|
||||||
// Create sync port
|
// Create sync port
|
||||||
std::thread(std::bind(
|
std::thread(std::bind(
|
||||||
&do_sync_listen,
|
&do_sync_listen,
|
||||||
std::ref(ios),
|
std::ref(ioc),
|
||||||
tcp::endpoint{
|
tcp::endpoint{
|
||||||
address,
|
address,
|
||||||
static_cast<unsigned short>(port + 0u)}
|
static_cast<unsigned short>(port + 0u)}
|
||||||
@ -428,16 +439,16 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
// Create async port
|
// Create async port
|
||||||
std::make_shared<async_listener>(
|
std::make_shared<async_listener>(
|
||||||
ios,
|
ioc,
|
||||||
tcp::endpoint{
|
tcp::endpoint{
|
||||||
address,
|
address,
|
||||||
static_cast<unsigned short>(port + 1u)})->run();
|
static_cast<unsigned short>(port + 1u)})->run();
|
||||||
|
|
||||||
// Create coro port
|
// Create coro port
|
||||||
boost::asio::spawn(ios,
|
boost::asio::spawn(ioc,
|
||||||
std::bind(
|
std::bind(
|
||||||
&do_coro_listen,
|
&do_coro_listen,
|
||||||
std::ref(ios),
|
std::ref(ioc),
|
||||||
tcp::endpoint{
|
tcp::endpoint{
|
||||||
address,
|
address,
|
||||||
static_cast<unsigned short>(port + 2u)},
|
static_cast<unsigned short>(port + 2u)},
|
||||||
@ -448,11 +459,11 @@ int main(int argc, char* argv[])
|
|||||||
v.reserve(threads - 1);
|
v.reserve(threads - 1);
|
||||||
for(auto i = threads - 1; i > 0; --i)
|
for(auto i = threads - 1; i > 0; --i)
|
||||||
v.emplace_back(
|
v.emplace_back(
|
||||||
[&ios]
|
[&ioc]
|
||||||
{
|
{
|
||||||
ios.run();
|
ioc.run();
|
||||||
});
|
});
|
||||||
ios.run();
|
ioc.run();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include <boost/beast/core.hpp>
|
#include <boost/beast/core.hpp>
|
||||||
#include <boost/beast/websocket.hpp>
|
#include <boost/beast/websocket.hpp>
|
||||||
#include <boost/beast/websocket/ssl.hpp>
|
#include <boost/beast/websocket/ssl.hpp>
|
||||||
|
#include <boost/asio/bind_executor.hpp>
|
||||||
#include <boost/asio/coroutine.hpp>
|
#include <boost/asio/coroutine.hpp>
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
#include <boost/asio/ssl/stream.hpp>
|
#include <boost/asio/ssl/stream.hpp>
|
||||||
@ -51,7 +52,8 @@ class session
|
|||||||
{
|
{
|
||||||
tcp::socket socket_;
|
tcp::socket socket_;
|
||||||
websocket::stream<ssl::stream<tcp::socket&>> ws_;
|
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_;
|
boost::beast::multi_buffer buffer_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -59,7 +61,7 @@ public:
|
|||||||
session(tcp::socket socket, ssl::context& ctx)
|
session(tcp::socket socket, ssl::context& ctx)
|
||||||
: socket_(std::move(socket))
|
: socket_(std::move(socket))
|
||||||
, ws_(socket_, ctx)
|
, ws_(socket_, ctx)
|
||||||
, strand_(ws_.get_io_service())
|
, strand_(ws_.get_executor())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,21 +85,25 @@ public:
|
|||||||
// Perform the SSL handshake
|
// Perform the SSL handshake
|
||||||
yield ws_.next_layer().async_handshake(
|
yield ws_.next_layer().async_handshake(
|
||||||
ssl::stream_base::server,
|
ssl::stream_base::server,
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::loop,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&session::loop,
|
||||||
0)));
|
shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
0)));
|
||||||
if(ec)
|
if(ec)
|
||||||
return fail(ec, "handshake");
|
return fail(ec, "handshake");
|
||||||
|
|
||||||
// Accept the websocket handshake
|
// Accept the websocket handshake
|
||||||
yield ws_.async_accept(
|
yield ws_.async_accept(
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::loop,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&session::loop,
|
||||||
0)));
|
shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
0)));
|
||||||
if(ec)
|
if(ec)
|
||||||
return fail(ec, "accept");
|
return fail(ec, "accept");
|
||||||
|
|
||||||
@ -106,11 +112,13 @@ public:
|
|||||||
// Read a message into our buffer
|
// Read a message into our buffer
|
||||||
yield ws_.async_read(
|
yield ws_.async_read(
|
||||||
buffer_,
|
buffer_,
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::loop,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&session::loop,
|
||||||
std::placeholders::_2)));
|
shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2)));
|
||||||
if(ec == websocket::error::closed)
|
if(ec == websocket::error::closed)
|
||||||
{
|
{
|
||||||
// This indicates that the session was closed
|
// This indicates that the session was closed
|
||||||
@ -123,11 +131,13 @@ public:
|
|||||||
ws_.text(ws_.got_text());
|
ws_.text(ws_.got_text());
|
||||||
yield ws_.async_write(
|
yield ws_.async_write(
|
||||||
buffer_.data(),
|
buffer_.data(),
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::loop,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&session::loop,
|
||||||
std::placeholders::_2)));
|
shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2)));
|
||||||
if(ec)
|
if(ec)
|
||||||
return fail(ec, "write");
|
return fail(ec, "write");
|
||||||
|
|
||||||
@ -152,12 +162,12 @@ class listener
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
listener(
|
listener(
|
||||||
boost::asio::io_service& ios,
|
boost::asio::io_context& ioc,
|
||||||
ssl::context& ctx,
|
ssl::context& ctx,
|
||||||
tcp::endpoint endpoint)
|
tcp::endpoint endpoint)
|
||||||
: ctx_(ctx)
|
: ctx_(ctx)
|
||||||
, acceptor_(ios)
|
, acceptor_(ioc)
|
||||||
, socket_(ios)
|
, socket_(ioc)
|
||||||
{
|
{
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
|
|
||||||
@ -179,7 +189,7 @@ public:
|
|||||||
|
|
||||||
// Start listening for connections
|
// Start listening for connections
|
||||||
acceptor_.listen(
|
acceptor_.listen(
|
||||||
boost::asio::socket_base::max_connections, ec);
|
boost::asio::socket_base::max_listen_connections, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
fail(ec, "listen");
|
fail(ec, "listen");
|
||||||
@ -238,12 +248,12 @@ int main(int argc, char* argv[])
|
|||||||
" websocket-server-async-ssl 0.0.0.0 8080 1\n";
|
" websocket-server-async-ssl 0.0.0.0 8080 1\n";
|
||||||
return EXIT_FAILURE;
|
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 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
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios{threads};
|
boost::asio::io_context ioc{threads};
|
||||||
|
|
||||||
// The SSL context is required, and holds certificates
|
// The SSL context is required, and holds certificates
|
||||||
ssl::context ctx{ssl::context::sslv23};
|
ssl::context ctx{ssl::context::sslv23};
|
||||||
@ -252,18 +262,18 @@ int main(int argc, char* argv[])
|
|||||||
load_server_certificate(ctx);
|
load_server_certificate(ctx);
|
||||||
|
|
||||||
// Create and launch a listening port
|
// 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
|
// Run the I/O service on the requested number of threads
|
||||||
std::vector<std::thread> v;
|
std::vector<std::thread> v;
|
||||||
v.reserve(threads - 1);
|
v.reserve(threads - 1);
|
||||||
for(auto i = threads - 1; i > 0; --i)
|
for(auto i = threads - 1; i > 0; --i)
|
||||||
v.emplace_back(
|
v.emplace_back(
|
||||||
[&ios]
|
[&ioc]
|
||||||
{
|
{
|
||||||
ios.run();
|
ioc.run();
|
||||||
});
|
});
|
||||||
ios.run();
|
ioc.run();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include <boost/beast/core.hpp>
|
#include <boost/beast/core.hpp>
|
||||||
#include <boost/beast/websocket.hpp>
|
#include <boost/beast/websocket.hpp>
|
||||||
|
#include <boost/asio/bind_executor.hpp>
|
||||||
#include <boost/asio/coroutine.hpp>
|
#include <boost/asio/coroutine.hpp>
|
||||||
#include <boost/asio/strand.hpp>
|
#include <boost/asio/strand.hpp>
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
@ -45,7 +46,8 @@ class session
|
|||||||
, public std::enable_shared_from_this<session>
|
, public std::enable_shared_from_this<session>
|
||||||
{
|
{
|
||||||
websocket::stream<tcp::socket> ws_;
|
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_;
|
boost::beast::multi_buffer buffer_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -53,7 +55,7 @@ public:
|
|||||||
explicit
|
explicit
|
||||||
session(tcp::socket socket)
|
session(tcp::socket socket)
|
||||||
: ws_(std::move(socket))
|
: ws_(std::move(socket))
|
||||||
, strand_(ws_.get_io_service())
|
, strand_(ws_.get_executor())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,11 +77,13 @@ public:
|
|||||||
{
|
{
|
||||||
// Accept the websocket handshake
|
// Accept the websocket handshake
|
||||||
yield ws_.async_accept(
|
yield ws_.async_accept(
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::loop,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&session::loop,
|
||||||
0)));
|
shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
0)));
|
||||||
if(ec)
|
if(ec)
|
||||||
return fail(ec, "accept");
|
return fail(ec, "accept");
|
||||||
|
|
||||||
@ -88,11 +92,13 @@ public:
|
|||||||
// Read a message into our buffer
|
// Read a message into our buffer
|
||||||
yield ws_.async_read(
|
yield ws_.async_read(
|
||||||
buffer_,
|
buffer_,
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::loop,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&session::loop,
|
||||||
std::placeholders::_2)));
|
shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2)));
|
||||||
if(ec == websocket::error::closed)
|
if(ec == websocket::error::closed)
|
||||||
{
|
{
|
||||||
// This indicates that the session was closed
|
// This indicates that the session was closed
|
||||||
@ -105,11 +111,13 @@ public:
|
|||||||
ws_.text(ws_.got_text());
|
ws_.text(ws_.got_text());
|
||||||
yield ws_.async_write(
|
yield ws_.async_write(
|
||||||
buffer_.data(),
|
buffer_.data(),
|
||||||
strand_.wrap(std::bind(
|
boost::asio::bind_executor(
|
||||||
&session::loop,
|
strand_,
|
||||||
shared_from_this(),
|
std::bind(
|
||||||
std::placeholders::_1,
|
&session::loop,
|
||||||
std::placeholders::_2)));
|
shared_from_this(),
|
||||||
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2)));
|
||||||
if(ec)
|
if(ec)
|
||||||
return fail(ec, "write");
|
return fail(ec, "write");
|
||||||
|
|
||||||
@ -133,10 +141,10 @@ class listener
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
listener(
|
listener(
|
||||||
boost::asio::io_service& ios,
|
boost::asio::io_context& ioc,
|
||||||
tcp::endpoint endpoint)
|
tcp::endpoint endpoint)
|
||||||
: acceptor_(ios)
|
: acceptor_(ioc)
|
||||||
, socket_(ios)
|
, socket_(ioc)
|
||||||
{
|
{
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
|
|
||||||
@ -158,7 +166,7 @@ public:
|
|||||||
|
|
||||||
// Start listening for connections
|
// Start listening for connections
|
||||||
acceptor_.listen(
|
acceptor_.listen(
|
||||||
boost::asio::socket_base::max_connections, ec);
|
boost::asio::socket_base::max_listen_connections, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
fail(ec, "listen");
|
fail(ec, "listen");
|
||||||
@ -217,26 +225,26 @@ int main(int argc, char* argv[])
|
|||||||
" websocket-server-stackless 0.0.0.0 8080 1\n";
|
" websocket-server-stackless 0.0.0.0 8080 1\n";
|
||||||
return EXIT_FAILURE;
|
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 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
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios{threads};
|
boost::asio::io_context ioc{threads};
|
||||||
|
|
||||||
// Create and launch a listening port
|
// 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
|
// Run the I/O service on the requested number of threads
|
||||||
std::vector<std::thread> v;
|
std::vector<std::thread> v;
|
||||||
v.reserve(threads - 1);
|
v.reserve(threads - 1);
|
||||||
for(auto i = threads - 1; i > 0; --i)
|
for(auto i = threads - 1; i > 0; --i)
|
||||||
v.emplace_back(
|
v.emplace_back(
|
||||||
[&ios]
|
[&ioc]
|
||||||
{
|
{
|
||||||
ios.run();
|
ioc.run();
|
||||||
});
|
});
|
||||||
ios.run();
|
ioc.run();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -87,11 +87,11 @@ int main(int argc, char* argv[])
|
|||||||
" websocket-server-sync-ssl 0.0.0.0 8080\n";
|
" websocket-server-sync-ssl 0.0.0.0 8080\n";
|
||||||
return EXIT_FAILURE;
|
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 port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||||
|
|
||||||
// The io_service is required for all I/O
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios{1};
|
boost::asio::io_context ioc{1};
|
||||||
|
|
||||||
// The SSL context is required, and holds certificates
|
// The SSL context is required, and holds certificates
|
||||||
ssl::context ctx{ssl::context::sslv23};
|
ssl::context ctx{ssl::context::sslv23};
|
||||||
@ -100,11 +100,11 @@ int main(int argc, char* argv[])
|
|||||||
load_server_certificate(ctx);
|
load_server_certificate(ctx);
|
||||||
|
|
||||||
// The acceptor receives incoming connections
|
// The acceptor receives incoming connections
|
||||||
tcp::acceptor acceptor{ios, {address, port}};
|
tcp::acceptor acceptor{ioc, {address, port}};
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
// This will receive the new connection
|
// This will receive the new connection
|
||||||
tcp::socket socket{ios};
|
tcp::socket socket{ioc};
|
||||||
|
|
||||||
// Block until we get a connection
|
// Block until we get a connection
|
||||||
acceptor.accept(socket);
|
acceptor.accept(socket);
|
||||||
|
@ -79,18 +79,18 @@ int main(int argc, char* argv[])
|
|||||||
" websocket-server-sync 0.0.0.0 8080\n";
|
" websocket-server-sync 0.0.0.0 8080\n";
|
||||||
return EXIT_FAILURE;
|
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 port = static_cast<unsigned short>(std::atoi(argv[2]));
|
||||||
|
|
||||||
// The io_service is required for all I/O
|
// The io_context is required for all I/O
|
||||||
boost::asio::io_service ios{1};
|
boost::asio::io_context ioc{1};
|
||||||
|
|
||||||
// The acceptor receives incoming connections
|
// The acceptor receives incoming connections
|
||||||
tcp::acceptor acceptor{ios, {address, port}};
|
tcp::acceptor acceptor{ioc, {address, port}};
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
// This will receive the new connection
|
// This will receive the new connection
|
||||||
tcp::socket socket{ios};
|
tcp::socket socket{ioc};
|
||||||
|
|
||||||
// Block until we get a connection
|
// Block until we get a connection
|
||||||
acceptor.accept(socket);
|
acceptor.accept(socket);
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
|
|
||||||
#include <boost/beast/core/detail/config.hpp>
|
#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/bind_handler.hpp>
|
||||||
#include <boost/beast/core/buffered_read_stream.hpp>
|
#include <boost/beast/core/buffered_read_stream.hpp>
|
||||||
#include <boost/beast/core/buffers_adapter.hpp>
|
#include <boost/beast/core/buffers_adapter.hpp>
|
||||||
@ -28,7 +27,6 @@
|
|||||||
#include <boost/beast/core/file_win32.hpp>
|
#include <boost/beast/core/file_win32.hpp>
|
||||||
#include <boost/beast/core/flat_buffer.hpp>
|
#include <boost/beast/core/flat_buffer.hpp>
|
||||||
#include <boost/beast/core/flat_static_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/handler_ptr.hpp>
|
||||||
#include <boost/beast/core/multi_buffer.hpp>
|
#include <boost/beast/core/multi_buffer.hpp>
|
||||||
#include <boost/beast/core/ostream.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
|
placeholders present in the list of bound arguments. Parameters
|
||||||
which are not matched to placeholders are silently discarded.
|
which are not matched to placeholders are silently discarded.
|
||||||
The passed handler and arguments are forwarded into the returned
|
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.
|
as the original handler.
|
||||||
|
|
||||||
Unlike `boost::asio::io_service::wrap`, the returned handler can
|
Unlike `boost::asio::io_context::wrap`, the returned handler can
|
||||||
be used in a subsequent call to `boost::asio::io_service::post`
|
be used in a subsequent call to `boost::asio::io_context::post`
|
||||||
instead of `boost::asio::io_service::dispatch`, to ensure that
|
instead of `boost::asio::io_context::dispatch`, to ensure that
|
||||||
the handler will not be invoked immediately by the calling
|
the handler will not be invoked immediately by the calling
|
||||||
function.
|
function.
|
||||||
|
|
||||||
@ -43,7 +43,8 @@ namespace beast {
|
|||||||
void
|
void
|
||||||
signal_aborted(AsyncReadStream& stream, ReadHandler&& handler)
|
signal_aborted(AsyncReadStream& stream, ReadHandler&& handler)
|
||||||
{
|
{
|
||||||
stream.get_io_service().post(
|
boost::asio::post(
|
||||||
|
stream.get_executor(),
|
||||||
bind_handler(std::forward<ReadHandler>(handler),
|
bind_handler(std::forward<ReadHandler>(handler),
|
||||||
boost::asio::error::operation_aborted, 0));
|
boost::asio::error::operation_aborted, 0));
|
||||||
}
|
}
|
||||||
|
@ -11,12 +11,12 @@
|
|||||||
#define BOOST_BEAST_BUFFERED_READ_STREAM_HPP
|
#define BOOST_BEAST_BUFFERED_READ_STREAM_HPP
|
||||||
|
|
||||||
#include <boost/beast/core/detail/config.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/error.hpp>
|
||||||
#include <boost/beast/core/multi_buffer.hpp>
|
#include <boost/beast/core/multi_buffer.hpp>
|
||||||
#include <boost/beast/core/type_traits.hpp>
|
#include <boost/beast/core/type_traits.hpp>
|
||||||
|
#include <boost/asio/async_result.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <boost/asio/io_service.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@ -91,7 +91,8 @@ namespace beast {
|
|||||||
template<class Stream, class DynamicBuffer>
|
template<class Stream, class DynamicBuffer>
|
||||||
class buffered_read_stream
|
class buffered_read_stream
|
||||||
{
|
{
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(
|
||||||
|
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
|
|
||||||
template<class Buffers, class Handler>
|
template<class Buffers, class Handler>
|
||||||
@ -163,11 +164,29 @@ public:
|
|||||||
return next_layer_.lowest_layer();
|
return next_layer_.lowest_layer();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the io_service associated with the object.
|
/** Get the executor associated with the object.
|
||||||
boost::asio::io_service&
|
|
||||||
get_io_service()
|
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.
|
/** Access the internal buffer.
|
||||||
@ -265,14 +284,11 @@ public:
|
|||||||
Regardless of whether the asynchronous operation completes
|
Regardless of whether the asynchronous operation completes
|
||||||
immediately or not, the handler will not be invoked from within
|
immediately or not, the handler will not be invoked from within
|
||||||
this function. Invocation of the handler will be performed in a
|
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>
|
template<class MutableBufferSequence, class ReadHandler>
|
||||||
#if BOOST_BEAST_DOXYGEN
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
void_or_deduced
|
ReadHandler, void(error_code))
|
||||||
#else
|
|
||||||
async_return_type<ReadHandler, void(error_code)>
|
|
||||||
#endif
|
|
||||||
async_read_some(MutableBufferSequence const& buffers,
|
async_read_some(MutableBufferSequence const& buffers,
|
||||||
ReadHandler&& handler);
|
ReadHandler&& handler);
|
||||||
|
|
||||||
@ -340,14 +356,11 @@ public:
|
|||||||
Regardless of whether the asynchronous operation completes
|
Regardless of whether the asynchronous operation completes
|
||||||
immediately or not, the handler will not be invoked from within
|
immediately or not, the handler will not be invoked from within
|
||||||
this function. Invocation of the handler will be performed in a
|
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>
|
template<class ConstBufferSequence, class WriteHandler>
|
||||||
#if BOOST_BEAST_DOXYGEN
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
void_or_deduced
|
WriteHandler, void(error_code))
|
||||||
#else
|
|
||||||
async_return_type<WriteHandler, void(error_code)>
|
|
||||||
#endif
|
|
||||||
async_write_some(ConstBufferSequence const& buffers,
|
async_write_some(ConstBufferSequence const& buffers,
|
||||||
WriteHandler&& handler);
|
WriteHandler&& handler);
|
||||||
};
|
};
|
||||||
|
@ -35,10 +35,12 @@ namespace beast {
|
|||||||
template<class MutableBufferSequence>
|
template<class MutableBufferSequence>
|
||||||
class buffers_adapter
|
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");
|
"MutableBufferSequence requirements not met");
|
||||||
|
|
||||||
using iter_type = typename MutableBufferSequence::const_iterator;
|
using iter_type = typename
|
||||||
|
detail::buffer_sequence_iterator<
|
||||||
|
MutableBufferSequence>::type;
|
||||||
|
|
||||||
MutableBufferSequence bs_;
|
MutableBufferSequence bs_;
|
||||||
iter_type begin_;
|
iter_type begin_;
|
||||||
|
@ -34,8 +34,8 @@ class buffers_prefix_view
|
|||||||
using buffers_type = typename
|
using buffers_type = typename
|
||||||
std::decay<BufferSequence>::type;
|
std::decay<BufferSequence>::type;
|
||||||
|
|
||||||
using iter_type =
|
using iter_type = typename
|
||||||
typename buffers_type::const_iterator;
|
detail::buffer_sequence_iterator<buffers_type>::type;
|
||||||
|
|
||||||
BufferSequence bs_;
|
BufferSequence bs_;
|
||||||
std::size_t size_;
|
std::size_t size_;
|
||||||
@ -141,10 +141,8 @@ boost::asio::const_buffer
|
|||||||
buffers_prefix(std::size_t size,
|
buffers_prefix(std::size_t size,
|
||||||
boost::asio::const_buffer buffer)
|
boost::asio::const_buffer buffer)
|
||||||
{
|
{
|
||||||
using boost::asio::buffer_cast;
|
return {buffer.data(),
|
||||||
using boost::asio::buffer_size;
|
(std::min)(size, buffer.size())};
|
||||||
return { buffer_cast<void const*>(buffer),
|
|
||||||
(std::min)(size, buffer_size(buffer)) };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a prefix of a mutable buffer.
|
/** Returns a prefix of a mutable buffer.
|
||||||
@ -166,10 +164,8 @@ boost::asio::mutable_buffer
|
|||||||
buffers_prefix(std::size_t size,
|
buffers_prefix(std::size_t size,
|
||||||
boost::asio::mutable_buffer buffer)
|
boost::asio::mutable_buffer buffer)
|
||||||
{
|
{
|
||||||
using boost::asio::buffer_cast;
|
return {buffer.data(),
|
||||||
using boost::asio::buffer_size;
|
(std::min)(size, buffer.size())};
|
||||||
return {buffer_cast<void*>(buffer),
|
|
||||||
(std::min)(size, buffer_size(buffer))};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a prefix of a buffer sequence.
|
/** Returns a prefix of a buffer sequence.
|
||||||
@ -203,8 +199,8 @@ typename std::enable_if<
|
|||||||
buffers_prefix(std::size_t size, BufferSequence const& buffers)
|
buffers_prefix(std::size_t size, BufferSequence const& buffers)
|
||||||
{
|
{
|
||||||
static_assert(
|
static_assert(
|
||||||
is_const_buffer_sequence<BufferSequence>::value ||
|
boost::asio::is_const_buffer_sequence<BufferSequence>::value ||
|
||||||
is_mutable_buffer_sequence<BufferSequence>::value,
|
boost::asio::is_mutable_buffer_sequence<BufferSequence>::value,
|
||||||
"BufferSequence requirements not met");
|
"BufferSequence requirements not met");
|
||||||
return buffers_prefix_view<BufferSequence>(size, buffers);
|
return buffers_prefix_view<BufferSequence>(size, buffers);
|
||||||
}
|
}
|
||||||
@ -221,13 +217,14 @@ buffers_prefix(std::size_t size, BufferSequence const& buffers)
|
|||||||
*/
|
*/
|
||||||
template<class BufferSequence>
|
template<class BufferSequence>
|
||||||
typename std::conditional<
|
typename std::conditional<
|
||||||
is_mutable_buffer_sequence<BufferSequence>::value,
|
boost::asio::is_mutable_buffer_sequence<BufferSequence>::value,
|
||||||
boost::asio::mutable_buffer,
|
boost::asio::mutable_buffer,
|
||||||
boost::asio::const_buffer>::type
|
boost::asio::const_buffer>::type
|
||||||
buffers_front(BufferSequence const& buffers)
|
buffers_front(BufferSequence const& buffers)
|
||||||
{
|
{
|
||||||
auto const first = buffers.begin();
|
auto const first =
|
||||||
if(first == buffers.end())
|
boost::asio::buffer_sequence_begin(buffers);
|
||||||
|
if(first == boost::asio::buffer_sequence_end(buffers))
|
||||||
return {};
|
return {};
|
||||||
return *first;
|
return *first;
|
||||||
}
|
}
|
||||||
|
@ -12,11 +12,11 @@
|
|||||||
|
|
||||||
#include <boost/beast/core/detail/config.hpp>
|
#include <boost/beast/core/detail/config.hpp>
|
||||||
#include <boost/beast/core/detail/in_place_init.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/asio/buffer.hpp>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <type_traits>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
@ -57,8 +57,8 @@ class buffers_suffix
|
|||||||
using buffers_type =
|
using buffers_type =
|
||||||
typename std::decay<BufferSequence>::type;
|
typename std::decay<BufferSequence>::type;
|
||||||
|
|
||||||
using iter_type =
|
using iter_type = typename
|
||||||
typename buffers_type::const_iterator;
|
detail::buffer_sequence_iterator<buffers_type>::type;
|
||||||
|
|
||||||
BufferSequence bs_;
|
BufferSequence bs_;
|
||||||
iter_type begin_;
|
iter_type begin_;
|
||||||
@ -67,7 +67,9 @@ class buffers_suffix
|
|||||||
template<class Deduced>
|
template<class Deduced>
|
||||||
buffers_suffix(Deduced&& other, std::size_t dist)
|
buffers_suffix(Deduced&& other, std::size_t dist)
|
||||||
: bs_(std::forward<Deduced>(other).bs_)
|
: 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_)
|
, skip_(other.skip_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#define BOOST_BEAST_BUFFERS_TO_STRING_HPP
|
#define BOOST_BEAST_BUFFERS_TO_STRING_HPP
|
||||||
|
|
||||||
#include <boost/beast/core/detail/config.hpp>
|
#include <boost/beast/core/detail/config.hpp>
|
||||||
|
#include <boost/beast/core/detail/type_traits.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -45,10 +46,10 @@ buffers_to_string(ConstBufferSequence const& buffers)
|
|||||||
{
|
{
|
||||||
std::string result;
|
std::string result;
|
||||||
result.reserve(boost::asio::buffer_size(buffers));
|
result.reserve(boost::asio::buffer_size(buffers));
|
||||||
for(boost::asio::const_buffer buffer : buffers)
|
for(boost::asio::const_buffer buffer :
|
||||||
result.append(
|
detail::buffers_range(buffers))
|
||||||
boost::asio::buffer_cast<char const*>(buffer),
|
result.append(reinterpret_cast<
|
||||||
boost::asio::buffer_size(buffer));
|
char const*>(buffer.data()), buffer.size());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,9 +11,9 @@
|
|||||||
#define BOOST_BEAST_DETAIL_BIND_HANDLER_HPP
|
#define BOOST_BEAST_DETAIL_BIND_HANDLER_HPP
|
||||||
|
|
||||||
#include <boost/beast/core/detail/integer_sequence.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_continuation_hook.hpp>
|
||||||
#include <boost/asio/handler_invoke_hook.hpp>
|
|
||||||
#include <boost/core/ignore_unused.hpp>
|
#include <boost/core/ignore_unused.hpp>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@ -24,13 +24,17 @@ namespace detail {
|
|||||||
|
|
||||||
/* Nullary handler that calls Handler with bound arguments.
|
/* 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.
|
guarantees as the original handler.
|
||||||
*/
|
*/
|
||||||
template<class Handler, class... Args>
|
template<class Handler, class... Args>
|
||||||
class bound_handler
|
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<
|
using args_type = std::tuple<
|
||||||
typename std::decay<Args>::type...>;
|
typename std::decay<Args>::type...>;
|
||||||
|
|
||||||
@ -101,6 +105,9 @@ private:
|
|||||||
public:
|
public:
|
||||||
using result_type = void;
|
using result_type = void;
|
||||||
|
|
||||||
|
using allocator_type =
|
||||||
|
boost::asio::associated_allocator_t<Handler>;
|
||||||
|
|
||||||
bound_handler(bound_handler&&) = default;
|
bound_handler(bound_handler&&) = default;
|
||||||
bound_handler(bound_handler const&) = 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>
|
template<class... Values>
|
||||||
void
|
void
|
||||||
operator()(Values&&... values)
|
operator()(Values&&... values)
|
||||||
@ -132,48 +153,30 @@ public:
|
|||||||
std::forward<Values>(values)...),
|
std::forward<Values>(values)...),
|
||||||
index_sequence_for<Args...>());
|
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
|
} // detail
|
||||||
} // beast
|
} // 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
|
} // boost
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#define BOOST_BEAST_DETAIL_BUFFERS_REF_HPP
|
#define BOOST_BEAST_DETAIL_BUFFERS_REF_HPP
|
||||||
|
|
||||||
#include <boost/beast/core/type_traits.hpp>
|
#include <boost/beast/core/type_traits.hpp>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
namespace beast {
|
namespace beast {
|
||||||
@ -23,11 +24,11 @@ class buffers_ref
|
|||||||
BufferSequence const* buffers_;
|
BufferSequence const* buffers_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using value_type =
|
using const_iterator = typename
|
||||||
typename BufferSequence::value_type;
|
buffer_sequence_iterator<BufferSequence>::type;
|
||||||
|
|
||||||
using const_iterator =
|
using value_type = typename std::iterator_traits<
|
||||||
typename BufferSequence::const_iterator;
|
const_iterator>::value_type;
|
||||||
|
|
||||||
buffers_ref(buffers_ref const&) = default;
|
buffers_ref(buffers_ref const&) = default;
|
||||||
buffers_ref& operator=(buffers_ref const&) = default;
|
buffers_ref& operator=(buffers_ref const&) = default;
|
||||||
@ -41,13 +42,13 @@ public:
|
|||||||
const_iterator
|
const_iterator
|
||||||
begin() const
|
begin() const
|
||||||
{
|
{
|
||||||
return buffers_->begin();
|
return boost::asio::buffer_sequence_begin(*buffers_);
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator
|
const_iterator
|
||||||
end() const
|
end() const
|
||||||
{
|
{
|
||||||
return buffers_->end();
|
return boost::asio::buffer_sequence_end(*buffers_);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -10,8 +10,10 @@
|
|||||||
#ifndef BOOST_BEAST_DETAIL_OSTREAM_HPP
|
#ifndef BOOST_BEAST_DETAIL_OSTREAM_HPP
|
||||||
#define 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/read_size.hpp>
|
||||||
|
#include <boost/beast/core/detail/type_traits.hpp>
|
||||||
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <streambuf>
|
#include <streambuf>
|
||||||
@ -46,11 +48,10 @@ std::ostream&
|
|||||||
operator<<(std::ostream& os,
|
operator<<(std::ostream& os,
|
||||||
buffers_helper<Buffers> const& v)
|
buffers_helper<Buffers> const& v)
|
||||||
{
|
{
|
||||||
using boost::asio::buffer_cast;
|
for(auto b : buffers_range(v.b_))
|
||||||
using boost::asio::buffer_size;
|
os.write(
|
||||||
for(boost::asio::const_buffer b : v.b_)
|
reinterpret_cast<char const*>(b.data()),
|
||||||
os.write(buffer_cast<char const*>(b),
|
b.size());
|
||||||
buffer_size(b));
|
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,14 +131,12 @@ private:
|
|||||||
void
|
void
|
||||||
prepare()
|
prepare()
|
||||||
{
|
{
|
||||||
using boost::asio::buffer_cast;
|
auto bs = buf_.prepare(
|
||||||
using boost::asio::buffer_size;
|
|
||||||
auto mbs = buf_.prepare(
|
|
||||||
read_size_or_throw(buf_, max_size));
|
read_size_or_throw(buf_, max_size));
|
||||||
auto const mb = *mbs.begin();
|
auto const b = buffers_front(bs);
|
||||||
auto const p = buffer_cast<CharT*>(mb);
|
auto const p = reinterpret_cast<CharT*>(b.data());
|
||||||
this->setp(p,
|
this->setp(p,
|
||||||
p + buffer_size(mb) / sizeof(CharT) - 1);
|
p + b.size() / sizeof(CharT) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -211,14 +210,12 @@ private:
|
|||||||
void
|
void
|
||||||
prepare()
|
prepare()
|
||||||
{
|
{
|
||||||
using boost::asio::buffer_cast;
|
auto bs = buf_.prepare(
|
||||||
using boost::asio::buffer_size;
|
|
||||||
auto mbs = buf_.prepare(
|
|
||||||
read_size_or_throw(buf_, max_size));
|
read_size_or_throw(buf_, max_size));
|
||||||
auto const mb = *mbs.begin();
|
auto const b = buffers_front(bs);
|
||||||
auto const p = buffer_cast<CharT*>(mb);
|
auto const p = reinterpret_cast<CharT*>(b.data());
|
||||||
this->setp(p,
|
this->setp(p,
|
||||||
p + buffer_size(mb) / sizeof(CharT) - 1);
|
p + b.size() / sizeof(CharT) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -12,38 +12,12 @@
|
|||||||
|
|
||||||
#include <boost/beast/core/error.hpp>
|
#include <boost/beast/core/error.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <boost/asio/io_service.hpp>
|
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#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 boost {
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@ -281,57 +255,17 @@ using ConstBufferSequence =
|
|||||||
using MutableBufferSequence =
|
using MutableBufferSequence =
|
||||||
BufferSequence<boost::asio::mutable_buffer>;
|
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>
|
template<class B1, class... Bn>
|
||||||
struct is_all_const_buffer_sequence
|
struct is_all_const_buffer_sequence
|
||||||
: std::integral_constant<bool,
|
: 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>
|
is_all_const_buffer_sequence<Bn...>::value>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class B1>
|
template<class B>
|
||||||
struct is_all_const_buffer_sequence<B1>
|
struct is_all_const_buffer_sequence<B>
|
||||||
: is_buffer_sequence<B1, boost::asio::const_buffer>
|
: boost::asio::is_const_buffer_sequence<B>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -346,6 +280,14 @@ struct common_buffers_type
|
|||||||
boost::asio::const_buffer>::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,
|
// Types that meet the requirements,
|
||||||
// for use with std::declval only.
|
// for use with std::declval only.
|
||||||
struct StreamHandler
|
struct StreamHandler
|
||||||
@ -356,6 +298,54 @@ struct StreamHandler
|
|||||||
using ReadHandler = StreamHandler;
|
using ReadHandler = StreamHandler;
|
||||||
using WriteHandler = 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
|
} // detail
|
||||||
} // beast
|
} // beast
|
||||||
} // boost
|
} // boost
|
||||||
|
@ -84,10 +84,10 @@ public:
|
|||||||
using allocator_type = Allocator;
|
using allocator_type = Allocator;
|
||||||
|
|
||||||
/// The type used to represent the input sequence as a list of buffers.
|
/// 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.
|
/// 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
|
/// Destructor
|
||||||
~basic_flat_buffer();
|
~basic_flat_buffer();
|
||||||
|
@ -52,13 +52,13 @@ public:
|
|||||||
|
|
||||||
This buffer sequence is guaranteed to have length 1.
|
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.
|
/** The type used to represent the output sequence as a list of buffers.
|
||||||
|
|
||||||
This buffer sequence is guaranteed to have length 1.
|
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
|
/** 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/read_size.hpp>
|
||||||
#include <boost/beast/core/type_traits.hpp>
|
#include <boost/beast/core/type_traits.hpp>
|
||||||
#include <boost/beast/core/detail/config.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_continuation_hook.hpp>
|
||||||
#include <boost/asio/handler_invoke_hook.hpp>
|
#include <boost/asio/post.hpp>
|
||||||
#include <boost/throw_exception.hpp>
|
#include <boost/throw_exception.hpp>
|
||||||
|
|
||||||
namespace boost {
|
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
|
void
|
||||||
operator()(error_code const& ec,
|
operator()(error_code const& ec,
|
||||||
std::size_t bytes_transferred);
|
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
|
friend
|
||||||
bool asio_handler_is_continuation(read_some_op* op)
|
bool asio_handler_is_continuation(read_some_op* op)
|
||||||
{
|
{
|
||||||
@ -77,14 +78,6 @@ public:
|
|||||||
return asio_handler_is_continuation(
|
return asio_handler_is_continuation(
|
||||||
std::addressof(op->h_));
|
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>
|
template<class Stream, class DynamicBuffer>
|
||||||
@ -116,9 +109,9 @@ read_some_op<MutableBufferSequence, Handler>::operator()(
|
|||||||
|
|
||||||
}
|
}
|
||||||
step_ = 3;
|
step_ = 3;
|
||||||
s_.get_io_service().post(
|
return boost::asio::post(
|
||||||
|
s_.get_executor(),
|
||||||
bind_handler(std::move(*this), ec, 0));
|
bind_handler(std::move(*this), ec, 0));
|
||||||
return;
|
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
// upcall
|
// upcall
|
||||||
@ -153,11 +146,11 @@ auto
|
|||||||
buffered_read_stream<Stream, DynamicBuffer>::
|
buffered_read_stream<Stream, DynamicBuffer>::
|
||||||
async_write_some(ConstBufferSequence const& buffers,
|
async_write_some(ConstBufferSequence const& buffers,
|
||||||
WriteHandler&& handler) ->
|
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,
|
static_assert(is_async_write_stream<next_layer_type>::value,
|
||||||
"AsyncWriteStream requirements not met");
|
"AsyncWriteStream requirements not met");
|
||||||
static_assert(is_const_buffer_sequence<
|
static_assert(boost::asio::is_const_buffer_sequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
"ConstBufferSequence requirements not met");
|
"ConstBufferSequence requirements not met");
|
||||||
static_assert(is_completion_handler<WriteHandler,
|
static_assert(is_completion_handler<WriteHandler,
|
||||||
@ -176,7 +169,7 @@ read_some(
|
|||||||
{
|
{
|
||||||
static_assert(is_sync_read_stream<next_layer_type>::value,
|
static_assert(is_sync_read_stream<next_layer_type>::value,
|
||||||
"SyncReadStream requirements not met");
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_mutable_buffer_sequence<
|
static_assert(boost::asio::is_mutable_buffer_sequence<
|
||||||
MutableBufferSequence>::value,
|
MutableBufferSequence>::value,
|
||||||
"MutableBufferSequence requirements not met");
|
"MutableBufferSequence requirements not met");
|
||||||
error_code ec;
|
error_code ec;
|
||||||
@ -195,7 +188,7 @@ read_some(MutableBufferSequence const& buffers,
|
|||||||
{
|
{
|
||||||
static_assert(is_sync_read_stream<next_layer_type>::value,
|
static_assert(is_sync_read_stream<next_layer_type>::value,
|
||||||
"SyncReadStream requirements not met");
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_mutable_buffer_sequence<
|
static_assert(boost::asio::is_mutable_buffer_sequence<
|
||||||
MutableBufferSequence>::value,
|
MutableBufferSequence>::value,
|
||||||
"MutableBufferSequence requirements not met");
|
"MutableBufferSequence requirements not met");
|
||||||
using boost::asio::buffer_size;
|
using boost::asio::buffer_size;
|
||||||
@ -226,20 +219,20 @@ auto
|
|||||||
buffered_read_stream<Stream, DynamicBuffer>::
|
buffered_read_stream<Stream, DynamicBuffer>::
|
||||||
async_read_some(MutableBufferSequence const& buffers,
|
async_read_some(MutableBufferSequence const& buffers,
|
||||||
ReadHandler&& handler) ->
|
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,
|
static_assert(is_async_read_stream<next_layer_type>::value,
|
||||||
"Stream requirements not met");
|
"AsyncReadStream requirements not met");
|
||||||
static_assert(is_mutable_buffer_sequence<
|
static_assert(boost::asio::is_mutable_buffer_sequence<
|
||||||
MutableBufferSequence>::value,
|
MutableBufferSequence>::value,
|
||||||
"MutableBufferSequence requirements not met");
|
"MutableBufferSequence requirements not met");
|
||||||
if(buffer_.size() == 0 && capacity_ == 0)
|
if(buffer_.size() == 0 && capacity_ == 0)
|
||||||
return next_layer_.async_read_some(buffers,
|
return next_layer_.async_read_some(buffers,
|
||||||
std::forward<ReadHandler>(handler));
|
std::forward<ReadHandler>(handler));
|
||||||
async_completion<ReadHandler,
|
boost::asio::async_completion<ReadHandler,
|
||||||
void(error_code, std::size_t)> init{handler};
|
void(error_code, std::size_t)> init{handler};
|
||||||
read_some_op<MutableBufferSequence, handler_type<
|
read_some_op<MutableBufferSequence, BOOST_ASIO_HANDLER_TYPE(
|
||||||
ReadHandler, void(error_code, std::size_t)>>{
|
ReadHandler, void(error_code, std::size_t))>{
|
||||||
init.completion_handler, *this, buffers}(
|
init.completion_handler, *this, buffers}(
|
||||||
error_code{}, 0);
|
error_code{}, 0);
|
||||||
return init.result.get();
|
return init.result.get();
|
||||||
|
@ -90,11 +90,10 @@ public:
|
|||||||
reference
|
reference
|
||||||
operator*() const
|
operator*() const
|
||||||
{
|
{
|
||||||
using boost::asio::buffer_cast;
|
value_type const b = *it_;
|
||||||
using boost::asio::buffer_size;
|
return value_type{b.data(),
|
||||||
return value_type{buffer_cast<void const*>(*it_),
|
(ba_->out_ == boost::asio::buffer_sequence_end(ba_->bs_) ||
|
||||||
(ba_->out_ == ba_->bs_.end() ||
|
it_ != ba_->out_) ? b.size() : ba_->out_pos_} +
|
||||||
it_ != ba_->out_) ? buffer_size(*it_) : ba_->out_pos_} +
|
|
||||||
(it_ == ba_->begin_ ? ba_->in_pos_ : 0);
|
(it_ == ba_->begin_ ? ba_->in_pos_ : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,11 +232,10 @@ public:
|
|||||||
reference
|
reference
|
||||||
operator*() const
|
operator*() const
|
||||||
{
|
{
|
||||||
using boost::asio::buffer_cast;
|
value_type const b = *it_;
|
||||||
using boost::asio::buffer_size;
|
return value_type{b.data(),
|
||||||
return value_type{buffer_cast<void*>(*it_),
|
|
||||||
it_ == std::prev(ba_->end_) ?
|
it_ == std::prev(ba_->end_) ?
|
||||||
ba_->out_end_ : buffer_size(*it_)} +
|
ba_->out_end_ : b.size()} +
|
||||||
(it_ == ba_->out_ ? ba_->out_pos_ : 0);
|
(it_ == ba_->out_ ? ba_->out_pos_ : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,7 +286,9 @@ private:
|
|||||||
template<class MutableBufferSequence>
|
template<class MutableBufferSequence>
|
||||||
inline
|
inline
|
||||||
auto
|
auto
|
||||||
buffers_adapter<MutableBufferSequence>::mutable_buffers_type::begin() const ->
|
buffers_adapter<MutableBufferSequence>::
|
||||||
|
mutable_buffers_type::
|
||||||
|
begin() const ->
|
||||||
const_iterator
|
const_iterator
|
||||||
{
|
{
|
||||||
return const_iterator{*ba_, ba_->out_};
|
return const_iterator{*ba_, ba_->out_};
|
||||||
@ -297,7 +297,9 @@ buffers_adapter<MutableBufferSequence>::mutable_buffers_type::begin() const ->
|
|||||||
template<class MutableBufferSequence>
|
template<class MutableBufferSequence>
|
||||||
inline
|
inline
|
||||||
auto
|
auto
|
||||||
buffers_adapter<MutableBufferSequence>::mutable_buffers_type::end() const ->
|
buffers_adapter<MutableBufferSequence>::
|
||||||
|
mutable_buffers_type::
|
||||||
|
end() const ->
|
||||||
const_iterator
|
const_iterator
|
||||||
{
|
{
|
||||||
return const_iterator{*ba_, ba_->end_};
|
return const_iterator{*ba_, ba_->end_};
|
||||||
@ -309,9 +311,9 @@ template<class MutableBufferSequence>
|
|||||||
buffers_adapter<MutableBufferSequence>::buffers_adapter(
|
buffers_adapter<MutableBufferSequence>::buffers_adapter(
|
||||||
buffers_adapter&& other)
|
buffers_adapter&& other)
|
||||||
: buffers_adapter(std::move(other),
|
: buffers_adapter(std::move(other),
|
||||||
std::distance<iter_type>(other.bs_.begin(), other.begin_),
|
std::distance<iter_type>(boost::asio::buffer_sequence_begin(other.bs_), other.begin_),
|
||||||
std::distance<iter_type>(other.bs_.begin(), other.out_),
|
std::distance<iter_type>(boost::asio::buffer_sequence_begin(other.bs_), other.out_),
|
||||||
std::distance<iter_type>(other.bs_.begin(), other.end_))
|
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<MutableBufferSequence>::buffers_adapter(
|
||||||
buffers_adapter const& other)
|
buffers_adapter const& other)
|
||||||
: buffers_adapter(other,
|
: buffers_adapter(other,
|
||||||
std::distance<iter_type>(other.bs_.begin(), other.begin_),
|
std::distance<iter_type>(boost::asio::buffer_sequence_begin(other.bs_), other.begin_),
|
||||||
std::distance<iter_type>(other.bs_.begin(), other.out_),
|
std::distance<iter_type>(boost::asio::buffer_sequence_begin(other.bs_), other.out_),
|
||||||
std::distance<iter_type>(other.bs_.begin(), other.end_))
|
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&
|
buffers_adapter&& other) -> buffers_adapter&
|
||||||
{
|
{
|
||||||
auto const nbegin = std::distance<iter_type>(
|
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>(
|
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>(
|
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_);
|
bs_ = std::move(other.bs_);
|
||||||
begin_ = std::next(bs_.begin(), nbegin);
|
begin_ = std::next(boost::asio::buffer_sequence_begin(bs_), nbegin);
|
||||||
out_ = std::next(bs_.begin(), nout);
|
out_ = std::next(boost::asio::buffer_sequence_begin(bs_), nout);
|
||||||
end_ = std::next(bs_.begin(), nend);
|
end_ = std::next(boost::asio::buffer_sequence_begin(bs_), nend);
|
||||||
max_size_ = other.max_size_;
|
max_size_ = other.max_size_;
|
||||||
in_pos_ = other.in_pos_;
|
in_pos_ = other.in_pos_;
|
||||||
in_size_ = other.in_size_;
|
in_size_ = other.in_size_;
|
||||||
@ -354,15 +359,18 @@ buffers_adapter<MutableBufferSequence>::operator=(
|
|||||||
buffers_adapter const& other) -> buffers_adapter&
|
buffers_adapter const& other) -> buffers_adapter&
|
||||||
{
|
{
|
||||||
auto const nbegin = std::distance<iter_type>(
|
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>(
|
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>(
|
auto const nend = std::distance<iter_type>(
|
||||||
other.bs_.begin(), other.end_);
|
boost::asio::buffer_sequence_begin(other.bs_),
|
||||||
|
other.end_);
|
||||||
bs_ = other.bs_;
|
bs_ = other.bs_;
|
||||||
begin_ = std::next(bs_.begin(), nbegin);
|
begin_ = std::next(boost::asio::buffer_sequence_begin(bs_), nbegin);
|
||||||
out_ = std::next(bs_.begin(), nout);
|
out_ = std::next(boost::asio::buffer_sequence_begin(bs_), nout);
|
||||||
end_ = std::next(bs_.begin(), nend);
|
end_ = std::next(boost::asio::buffer_sequence_begin(bs_), nend);
|
||||||
max_size_ = other.max_size_;
|
max_size_ = other.max_size_;
|
||||||
in_pos_ = other.in_pos_;
|
in_pos_ = other.in_pos_;
|
||||||
in_size_ = other.in_size_;
|
in_size_ = other.in_size_;
|
||||||
@ -375,9 +383,9 @@ template<class MutableBufferSequence>
|
|||||||
buffers_adapter<MutableBufferSequence>::buffers_adapter(
|
buffers_adapter<MutableBufferSequence>::buffers_adapter(
|
||||||
MutableBufferSequence const& bs)
|
MutableBufferSequence const& bs)
|
||||||
: bs_(bs)
|
: bs_(bs)
|
||||||
, begin_(bs_.begin())
|
, begin_(boost::asio::buffer_sequence_begin(bs_))
|
||||||
, out_(bs_.begin())
|
, out_ (boost::asio::buffer_sequence_begin(bs_))
|
||||||
, end_(bs_.begin())
|
, end_ (boost::asio::buffer_sequence_begin(bs_))
|
||||||
, max_size_(boost::asio::buffer_size(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;
|
using boost::asio::buffer_size;
|
||||||
end_ = out_;
|
end_ = out_;
|
||||||
if(end_ != bs_.end())
|
if(end_ != boost::asio::buffer_sequence_end(bs_))
|
||||||
{
|
{
|
||||||
auto size = buffer_size(*end_) - out_pos_;
|
auto size = buffer_size(*end_) - out_pos_;
|
||||||
if(n > size)
|
if(n > size)
|
||||||
{
|
{
|
||||||
n -= size;
|
n -= size;
|
||||||
while(++end_ != bs_.end())
|
while(++end_ !=
|
||||||
|
boost::asio::buffer_sequence_end(bs_))
|
||||||
{
|
{
|
||||||
size = buffer_size(*end_);
|
size = buffer_size(*end_);
|
||||||
if(n < size)
|
if(n < size)
|
||||||
|
@ -30,7 +30,7 @@ class buffers_cat_view<Bn...>::const_iterator
|
|||||||
std::size_t n_;
|
std::size_t n_;
|
||||||
std::tuple<Bn...> const* bn_;
|
std::tuple<Bn...> const* bn_;
|
||||||
std::array<char, detail::max_sizeof<
|
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...>;
|
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>;
|
using C = std::integral_constant<std::size_t, I>;
|
||||||
|
|
||||||
template<std::size_t I>
|
template<std::size_t I>
|
||||||
using iter_t = typename std::tuple_element<
|
using iter_t = typename detail::buffer_sequence_iterator<
|
||||||
I, std::tuple<Bn...>>::type::const_iterator;
|
typename std::tuple_element<I, std::tuple<Bn...>>::type>::type;
|
||||||
|
|
||||||
template<std::size_t I>
|
template<std::size_t I>
|
||||||
iter_t<I>&
|
iter_t<I>&
|
||||||
@ -123,7 +123,8 @@ private:
|
|||||||
{
|
{
|
||||||
n_ = I;
|
n_ = I;
|
||||||
new(&buf_[0]) iter_t<I>{
|
new(&buf_[0]) iter_t<I>{
|
||||||
std::get<I>(*bn_).begin()};
|
boost::asio::buffer_sequence_begin(
|
||||||
|
std::get<I>(*bn_))};
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
construct(C<I+1>{});
|
construct(C<I+1>{});
|
||||||
@ -138,7 +139,8 @@ private:
|
|||||||
{
|
{
|
||||||
n_ = I;
|
n_ = I;
|
||||||
new(&buf_[0]) iter_t<I>{
|
new(&buf_[0]) iter_t<I>{
|
||||||
std::get<I>(*bn_).end()};
|
boost::asio::buffer_sequence_end(
|
||||||
|
std::get<I>(*bn_))};
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
BOOST_THROW_EXCEPTION(std::logic_error{
|
BOOST_THROW_EXCEPTION(std::logic_error{
|
||||||
@ -154,7 +156,8 @@ private:
|
|||||||
{
|
{
|
||||||
n_ = I;
|
n_ = I;
|
||||||
new(&buf_[0]) iter_t<I>{
|
new(&buf_[0]) iter_t<I>{
|
||||||
std::get<I>(*bn_).end()};
|
boost::asio::buffer_sequence_end(
|
||||||
|
std::get<I>(*bn_))};
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rconstruct(C<I-1>{});
|
rconstruct(C<I-1>{});
|
||||||
@ -268,7 +271,8 @@ private:
|
|||||||
if(n_ == I)
|
if(n_ == I)
|
||||||
{
|
{
|
||||||
if(++iter<I>() !=
|
if(++iter<I>() !=
|
||||||
std::get<I>(*bn_).end())
|
boost::asio::buffer_sequence_end(
|
||||||
|
std::get<I>(*bn_)))
|
||||||
return;
|
return;
|
||||||
using Iter = iter_t<I>;
|
using Iter = iter_t<I>;
|
||||||
iter<I>().~Iter();
|
iter<I>().~Iter();
|
||||||
@ -292,7 +296,9 @@ private:
|
|||||||
{
|
{
|
||||||
if(n_ == I)
|
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>();
|
--iter<I>();
|
||||||
return;
|
return;
|
||||||
@ -309,7 +315,9 @@ private:
|
|||||||
decrement(C<0> const&)
|
decrement(C<0> const&)
|
||||||
{
|
{
|
||||||
auto constexpr I = 0;
|
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>();
|
--iter<I>();
|
||||||
return;
|
return;
|
||||||
|
@ -27,10 +27,8 @@ boost::asio::const_buffer
|
|||||||
buffers_prefix(std::size_t size,
|
buffers_prefix(std::size_t size,
|
||||||
boost::asio::const_buffer buffer)
|
boost::asio::const_buffer buffer)
|
||||||
{
|
{
|
||||||
using boost::asio::buffer_cast;
|
return {buffer.data(),
|
||||||
using boost::asio::buffer_size;
|
(std::min)(size, buffer.size())};
|
||||||
return {buffer_cast<void const*>(buffer),
|
|
||||||
(std::min)(size, buffer_size(buffer))};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
@ -38,10 +36,8 @@ boost::asio::mutable_buffer
|
|||||||
buffers_prefix(std::size_t size,
|
buffers_prefix(std::size_t size,
|
||||||
boost::asio::mutable_buffer buffer)
|
boost::asio::mutable_buffer buffer)
|
||||||
{
|
{
|
||||||
using boost::asio::buffer_cast;
|
return {buffer.data(),
|
||||||
using boost::asio::buffer_size;
|
(std::min)(size, buffer.size())};
|
||||||
return {buffer_cast<void*>(buffer),
|
|
||||||
(std::min)(size, buffer_size(buffer))};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
@ -138,7 +134,7 @@ private:
|
|||||||
std::false_type)
|
std::false_type)
|
||||||
: b_(&b)
|
: b_(&b)
|
||||||
, remain_(b_->size_)
|
, 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)
|
setup(std::size_t size)
|
||||||
{
|
{
|
||||||
size_ = 0;
|
size_ = 0;
|
||||||
end_ = bs_.begin();
|
end_ = boost::asio::buffer_sequence_begin(bs_);
|
||||||
auto const last = bs_.end();
|
auto const last = bs_.end();
|
||||||
while(end_ != last)
|
while(end_ != last)
|
||||||
{
|
{
|
||||||
@ -170,7 +166,8 @@ buffers_prefix_view<BufferSequence>::
|
|||||||
buffers_prefix_view(buffers_prefix_view&& other)
|
buffers_prefix_view(buffers_prefix_view&& other)
|
||||||
: buffers_prefix_view(std::move(other),
|
: buffers_prefix_view(std::move(other),
|
||||||
std::distance<iter_type>(
|
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(buffers_prefix_view const& other)
|
||||||
: buffers_prefix_view(other,
|
: buffers_prefix_view(other,
|
||||||
std::distance<iter_type>(
|
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&
|
buffers_prefix_view&
|
||||||
{
|
{
|
||||||
auto const dist = std::distance<iter_type>(
|
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_);
|
bs_ = std::move(other.bs_);
|
||||||
size_ = other.size_;
|
size_ = other.size_;
|
||||||
end_ = std::next(bs_.begin(), dist);
|
end_ = std::next(
|
||||||
|
boost::asio::buffer_sequence_begin(bs_),
|
||||||
|
dist);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,10 +205,13 @@ operator=(buffers_prefix_view const& other) ->
|
|||||||
buffers_prefix_view&
|
buffers_prefix_view&
|
||||||
{
|
{
|
||||||
auto const dist = std::distance<iter_type>(
|
auto const dist = std::distance<iter_type>(
|
||||||
other.bs_.begin(), other.end_);
|
boost::asio::buffer_sequence_begin(other.bs_),
|
||||||
|
other.end_);
|
||||||
bs_ = other.bs_;
|
bs_ = other.bs_;
|
||||||
size_ = other.size_;
|
size_ = other.size_;
|
||||||
end_ = std::next(bs_.begin(), dist);
|
end_ = std::next(
|
||||||
|
boost::asio::buffer_sequence_begin(bs_),
|
||||||
|
dist);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,8 +25,8 @@ class buffers_suffix<Buffers>::const_iterator
|
|||||||
{
|
{
|
||||||
friend class buffers_suffix<Buffers>;
|
friend class buffers_suffix<Buffers>;
|
||||||
|
|
||||||
using iter_type =
|
using iter_type = typename
|
||||||
typename Buffers::const_iterator;
|
detail::buffer_sequence_iterator<Buffers>::type;
|
||||||
|
|
||||||
iter_type it_;
|
iter_type it_;
|
||||||
buffers_suffix const* b_ = nullptr;
|
buffers_suffix const* b_ = nullptr;
|
||||||
@ -117,7 +117,7 @@ private:
|
|||||||
template<class Buffers>
|
template<class Buffers>
|
||||||
buffers_suffix<Buffers>::
|
buffers_suffix<Buffers>::
|
||||||
buffers_suffix()
|
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(buffers_suffix&& other)
|
||||||
: buffers_suffix(std::move(other),
|
: buffers_suffix(std::move(other),
|
||||||
std::distance<iter_type>(
|
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(buffers_suffix const& other)
|
||||||
: buffers_suffix(other,
|
: buffers_suffix(other,
|
||||||
std::distance<iter_type>(
|
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>::
|
||||||
buffers_suffix(Buffers const& bs)
|
buffers_suffix(Buffers const& bs)
|
||||||
: bs_(bs)
|
: bs_(bs)
|
||||||
, begin_(bs_.begin())
|
, begin_(boost::asio::buffer_sequence_begin(bs_))
|
||||||
{
|
{
|
||||||
static_assert(
|
static_assert(
|
||||||
is_const_buffer_sequence<Buffers>::value||
|
boost::asio::is_const_buffer_sequence<Buffers>::value||
|
||||||
is_mutable_buffer_sequence<Buffers>::value,
|
boost::asio::is_mutable_buffer_sequence<Buffers>::value,
|
||||||
"BufferSequence requirements not met");
|
"BufferSequence requirements not met");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,7 +158,7 @@ template<class... Args>
|
|||||||
buffers_suffix<Buffers>::
|
buffers_suffix<Buffers>::
|
||||||
buffers_suffix(boost::in_place_init_t, Args&&... args)
|
buffers_suffix(boost::in_place_init_t, Args&&... args)
|
||||||
: bs_(std::forward<Args>(args)...)
|
: bs_(std::forward<Args>(args)...)
|
||||||
, begin_(bs_.begin())
|
, begin_(boost::asio::buffer_sequence_begin(bs_))
|
||||||
{
|
{
|
||||||
static_assert(sizeof...(Args) > 0,
|
static_assert(sizeof...(Args) > 0,
|
||||||
"Missing constructor arguments");
|
"Missing constructor arguments");
|
||||||
@ -172,9 +174,12 @@ operator=(buffers_suffix&& other) ->
|
|||||||
buffers_suffix&
|
buffers_suffix&
|
||||||
{
|
{
|
||||||
auto const dist = std::distance<iter_type>(
|
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_);
|
bs_ = std::move(other.bs_);
|
||||||
begin_ = std::next(bs_.begin(), dist);
|
begin_ = std::next(
|
||||||
|
boost::asio::buffer_sequence_begin(bs_),
|
||||||
|
dist);
|
||||||
skip_ = other.skip_;
|
skip_ = other.skip_;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -186,9 +191,11 @@ operator=(buffers_suffix const& other) ->
|
|||||||
buffers_suffix&
|
buffers_suffix&
|
||||||
{
|
{
|
||||||
auto const dist = std::distance<iter_type>(
|
auto const dist = std::distance<iter_type>(
|
||||||
other.bs_.begin(), other.begin_);
|
boost::asio::buffer_sequence_begin(other.bs_),
|
||||||
|
other.begin_);
|
||||||
bs_ = other.bs_;
|
bs_ = other.bs_;
|
||||||
begin_ = std::next(bs_.begin(), dist);
|
begin_ = std::next(
|
||||||
|
boost::asio::buffer_sequence_begin(bs_), dist);
|
||||||
skip_ = other.skip_;
|
skip_ = other.skip_;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -210,7 +217,8 @@ buffers_suffix<Buffers>::
|
|||||||
end() const ->
|
end() const ->
|
||||||
const_iterator
|
const_iterator
|
||||||
{
|
{
|
||||||
return const_iterator{*this, bs_.end()};
|
return const_iterator{*this,
|
||||||
|
boost::asio::buffer_sequence_end(bs_)};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Buffers>
|
template<class Buffers>
|
||||||
@ -219,7 +227,9 @@ buffers_suffix<Buffers>::
|
|||||||
consume(std::size_t amount)
|
consume(std::size_t amount)
|
||||||
{
|
{
|
||||||
using boost::asio::buffer_size;
|
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 =
|
auto const len =
|
||||||
buffer_size(*begin_) - skip_;
|
buffer_size(*begin_) - skip_;
|
||||||
|
@ -10,9 +10,7 @@
|
|||||||
#ifndef BOOST_BEAST_IMPL_HANDLER_PTR_HPP
|
#ifndef BOOST_BEAST_IMPL_HANDLER_PTR_HPP
|
||||||
#define BOOST_BEAST_IMPL_HANDLER_PTR_HPP
|
#define BOOST_BEAST_IMPL_HANDLER_PTR_HPP
|
||||||
|
|
||||||
#include <boost/asio/handler_alloc_hook.hpp>
|
#include <boost/asio/associated_allocator.hpp>
|
||||||
#include <boost/asio/handler_continuation_hook.hpp>
|
|
||||||
#include <boost/asio/handler_invoke_hook.hpp>
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@ -27,10 +25,11 @@ P(DeducedHandler&& h, Args&&... args)
|
|||||||
: n(1)
|
: n(1)
|
||||||
, handler(std::forward<DeducedHandler>(h))
|
, handler(std::forward<DeducedHandler>(h))
|
||||||
{
|
{
|
||||||
using boost::asio::asio_handler_allocate;
|
typename std::allocator_traits<
|
||||||
t = reinterpret_cast<T*>(
|
boost::asio::associated_allocator_t<Handler>>::
|
||||||
asio_handler_allocate(
|
template rebind_alloc<T> alloc{
|
||||||
sizeof(T), std::addressof(handler)));
|
boost::asio::get_associated_allocator(handler)};
|
||||||
|
t = std::allocator_traits<decltype(alloc)>::allocate(alloc, 1);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
t = new(t) T{handler,
|
t = new(t) T{handler,
|
||||||
@ -38,9 +37,8 @@ P(DeducedHandler&& h, Args&&... args)
|
|||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
using boost::asio::asio_handler_deallocate;
|
std::allocator_traits<
|
||||||
asio_handler_deallocate(
|
decltype(alloc)>::deallocate(alloc, t, 1);
|
||||||
t, sizeof(T), std::addressof(handler));
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,9 +54,13 @@ handler_ptr<T, Handler>::
|
|||||||
if(p_->t)
|
if(p_->t)
|
||||||
{
|
{
|
||||||
p_->t->~T();
|
p_->t->~T();
|
||||||
using boost::asio::asio_handler_deallocate;
|
typename std::allocator_traits<
|
||||||
asio_handler_deallocate(
|
boost::asio::associated_allocator_t<Handler>>::
|
||||||
p_->t, sizeof(T), std::addressof(p_->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_;
|
delete p_;
|
||||||
}
|
}
|
||||||
@ -108,9 +110,13 @@ release_handler() ->
|
|||||||
BOOST_ASSERT(p_);
|
BOOST_ASSERT(p_);
|
||||||
BOOST_ASSERT(p_->t);
|
BOOST_ASSERT(p_->t);
|
||||||
p_->t->~T();
|
p_->t->~T();
|
||||||
using boost::asio::asio_handler_deallocate;
|
typename std::allocator_traits<
|
||||||
asio_handler_deallocate(
|
boost::asio::associated_allocator_t<Handler>>::
|
||||||
p_->t, sizeof(T), std::addressof(p_->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_->t = nullptr;
|
||||||
return std::move(p_->handler);
|
return std::move(p_->handler);
|
||||||
}
|
}
|
||||||
@ -124,9 +130,13 @@ invoke(Args&&... args)
|
|||||||
BOOST_ASSERT(p_);
|
BOOST_ASSERT(p_);
|
||||||
BOOST_ASSERT(p_->t);
|
BOOST_ASSERT(p_->t);
|
||||||
p_->t->~T();
|
p_->t->~T();
|
||||||
using boost::asio::asio_handler_deallocate;
|
typename std::allocator_traits<
|
||||||
asio_handler_deallocate(
|
boost::asio::associated_allocator_t<Handler>>::
|
||||||
p_->t, sizeof(T), std::addressof(p_->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_->t = nullptr;
|
||||||
p_->handler(std::forward<Args>(args)...);
|
p_->handler(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,8 @@ std::size_t
|
|||||||
read_size(DynamicBuffer& buffer,
|
read_size(DynamicBuffer& buffer,
|
||||||
std::size_t max_size, std::false_type)
|
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");
|
"DynamicBuffer requirements not met");
|
||||||
BOOST_ASSERT(max_size >= 1);
|
BOOST_ASSERT(max_size >= 1);
|
||||||
auto const size = buffer.size();
|
auto const size = buffer.size();
|
||||||
|
@ -49,7 +49,7 @@ detail::buffers_helper<ConstBufferSequence>
|
|||||||
#endif
|
#endif
|
||||||
buffers(ConstBufferSequence const& b)
|
buffers(ConstBufferSequence const& b)
|
||||||
{
|
{
|
||||||
static_assert(is_const_buffer_sequence<
|
static_assert(boost::asio::is_const_buffer_sequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
"ConstBufferSequence requirements not met");
|
"ConstBufferSequence requirements not met");
|
||||||
return detail::buffers_helper<
|
return detail::buffers_helper<
|
||||||
@ -90,7 +90,8 @@ detail::ostream_helper<
|
|||||||
#endif
|
#endif
|
||||||
ostream(DynamicBuffer& buffer)
|
ostream(DynamicBuffer& buffer)
|
||||||
{
|
{
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(
|
||||||
|
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
return detail::ostream_helper<
|
return detail::ostream_helper<
|
||||||
DynamicBuffer, char, std::char_traits<char>,
|
DynamicBuffer, char, std::char_traits<char>,
|
||||||
|
@ -19,153 +19,6 @@
|
|||||||
namespace boost {
|
namespace boost {
|
||||||
namespace beast {
|
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
|
// 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
|
Metafunctions are used to perform compile time checking of template
|
||||||
types. This type will be `std::true_type` if `T` has the member
|
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>
|
template<class T>
|
||||||
void maybe_hello(T& t, std::true_type)
|
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>
|
template<class T>
|
||||||
void maybe_hello(T&, std::false_type)
|
void maybe_hello(T&, std::false_type)
|
||||||
{
|
{
|
||||||
// T does not have get_io_service
|
// T does not have get_executor
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void maybe_hello(T& t)
|
void maybe_hello(T& t)
|
||||||
{
|
{
|
||||||
maybe_hello(t, has_get_io_service<T>{});
|
maybe_hello(t, has_get_executor<T>{});
|
||||||
}
|
}
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
@ -244,24 +102,23 @@ using is_completion_handler = std::integral_constant<bool,
|
|||||||
@code
|
@code
|
||||||
struct stream
|
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,
|
static_assert(has_get_executor<stream>::value, "Missing get_executor member");
|
||||||
"Missing get_io_service member");
|
|
||||||
@endcode
|
@endcode
|
||||||
*/
|
*/
|
||||||
#if BOOST_BEAST_DOXYGEN
|
#if BOOST_BEAST_DOXYGEN
|
||||||
template<class T>
|
template<class T>
|
||||||
struct has_get_io_service : std::integral_constant<bool, ...>{};
|
struct has_get_executor : std::integral_constant<bool, ...>{};
|
||||||
#else
|
#else
|
||||||
template<class T, class = void>
|
template<class T, class = void>
|
||||||
struct has_get_io_service : std::false_type {};
|
struct has_get_executor : std::false_type {};
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
struct has_get_io_service<T, beast::detail::void_t<decltype(
|
struct has_get_executor<T, beast::detail::void_t<decltype(
|
||||||
detail::accept_rv<boost::asio::io_service&>(
|
std::declval<T&>().get_executor(),
|
||||||
std::declval<T&>().get_io_service()),
|
|
||||||
(void)0)>> : std::true_type {};
|
(void)0)>> : std::true_type {};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -350,7 +207,7 @@ struct is_async_read_stream<T, detail::void_t<decltype(
|
|||||||
std::declval<detail::MutableBufferSequence>(),
|
std::declval<detail::MutableBufferSequence>(),
|
||||||
std::declval<detail::ReadHandler>()),
|
std::declval<detail::ReadHandler>()),
|
||||||
(void)0)>> : std::integral_constant<bool,
|
(void)0)>> : std::integral_constant<bool,
|
||||||
has_get_io_service<T>::value
|
has_get_executor<T>::value
|
||||||
> {};
|
> {};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -394,7 +251,7 @@ struct is_async_write_stream<T, detail::void_t<decltype(
|
|||||||
std::declval<detail::ConstBufferSequence>(),
|
std::declval<detail::ConstBufferSequence>(),
|
||||||
std::declval<detail::WriteHandler>()),
|
std::declval<detail::WriteHandler>()),
|
||||||
(void)0)>> : std::integral_constant<bool,
|
(void)0)>> : std::integral_constant<bool,
|
||||||
has_get_io_service<T>::value
|
has_get_executor<T>::value
|
||||||
> {};
|
> {};
|
||||||
#endif
|
#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<std::size_t&>() = std::declval<T>().read_some(
|
||||||
std::declval<detail::MutableBufferSequence>(),
|
std::declval<detail::MutableBufferSequence>(),
|
||||||
std::declval<boost::system::error_code&>()),
|
std::declval<boost::system::error_code&>()),
|
||||||
(void)0)>> : std::integral_constant<bool,
|
(void)0)>> : std::true_type {};
|
||||||
has_get_io_service<T>::value
|
|
||||||
> {};
|
|
||||||
#endif
|
#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
|
Metafunctions are used to perform compile time checking of template
|
||||||
types. This type will be `std::true_type` if `T` meets the requirements,
|
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<std::size_t&>() = std::declval<T&>().write_some(
|
||||||
std::declval<detail::ConstBufferSequence>(),
|
std::declval<detail::ConstBufferSequence>(),
|
||||||
std::declval<boost::system::error_code&>()),
|
std::declval<boost::system::error_code&>()),
|
||||||
(void)0)>> : std::integral_constant<bool,
|
(void)0)>> : std::true_type {};
|
||||||
has_get_io_service<T>::value
|
|
||||||
> {};
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** Determine if `T` meets the requirements of @b AsyncStream.
|
/** Determine if `T` meets the requirements of @b AsyncStream.
|
||||||
|
@ -32,7 +32,8 @@ namespace http {
|
|||||||
template<class DynamicBuffer>
|
template<class DynamicBuffer>
|
||||||
struct basic_dynamic_body
|
struct basic_dynamic_body
|
||||||
{
|
{
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(
|
||||||
|
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
|
|
||||||
/** The type of container used for the body
|
/** The type of container used for the body
|
||||||
|
@ -143,7 +143,13 @@ public:
|
|||||||
|
|
||||||
/** Set the open file
|
/** 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
|
void
|
||||||
reset(File&& file, error_code& ec);
|
reset(File&& file, error_code& ec);
|
||||||
@ -229,7 +235,7 @@ public:
|
|||||||
// The type of buffer sequence returned by `get`.
|
// The type of buffer sequence returned by `get`.
|
||||||
//
|
//
|
||||||
using const_buffers_type =
|
using const_buffers_type =
|
||||||
boost::asio::const_buffers_1;
|
boost::asio::const_buffer;
|
||||||
|
|
||||||
// Constructor.
|
// Constructor.
|
||||||
//
|
//
|
||||||
@ -485,13 +491,13 @@ put(ConstBufferSequence const& buffers, error_code& ec)
|
|||||||
|
|
||||||
// Loop over all the buffers in the sequence,
|
// Loop over all the buffers in the sequence,
|
||||||
// and write each one to the file.
|
// 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
|
// Write this buffer to the file
|
||||||
|
boost::asio::const_buffer buffer = *it;
|
||||||
nwritten += body_.file_.write(
|
nwritten += body_.file_.write(
|
||||||
boost::asio::buffer_cast<void const*>(buffer),
|
buffer.data(), buffer.size(), ec);
|
||||||
boost::asio::buffer_size(buffer),
|
|
||||||
ec);
|
|
||||||
if(ec)
|
if(ec)
|
||||||
return nwritten;
|
return nwritten;
|
||||||
}
|
}
|
||||||
|
@ -515,7 +515,7 @@ public:
|
|||||||
|
|
||||||
#if ! BOOST_BEAST_DOXYGEN
|
#if ! BOOST_BEAST_DOXYGEN
|
||||||
std::size_t
|
std::size_t
|
||||||
put(boost::asio::const_buffers_1 const& buffer,
|
put(boost::asio::const_buffer const& buffer,
|
||||||
error_code& ec);
|
error_code& ec);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ struct buffer_body
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
using const_buffers_type =
|
using const_buffers_type =
|
||||||
boost::asio::const_buffers_1;
|
boost::asio::const_buffer;
|
||||||
|
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
|
@ -106,7 +106,7 @@ class chunk_header
|
|||||||
{
|
{
|
||||||
using view_type = buffers_cat_view<
|
using view_type = buffers_cat_view<
|
||||||
detail::chunk_size, // chunk-size
|
detail::chunk_size, // chunk-size
|
||||||
boost::asio::const_buffers_1, // chunk-extensions
|
boost::asio::const_buffer, // chunk-extensions
|
||||||
chunk_crlf>; // CRLF
|
chunk_crlf>; // CRLF
|
||||||
|
|
||||||
std::shared_ptr<
|
std::shared_ptr<
|
||||||
@ -285,7 +285,7 @@ class chunk_body
|
|||||||
{
|
{
|
||||||
using view_type = buffers_cat_view<
|
using view_type = buffers_cat_view<
|
||||||
detail::chunk_size, // chunk-size
|
detail::chunk_size, // chunk-size
|
||||||
boost::asio::const_buffers_1, // chunk-extensions
|
boost::asio::const_buffer, // chunk-extensions
|
||||||
chunk_crlf, // CRLF
|
chunk_crlf, // CRLF
|
||||||
ConstBufferSequence, // chunk-body
|
ConstBufferSequence, // chunk-body
|
||||||
chunk_crlf>; // CRLF
|
chunk_crlf>; // CRLF
|
||||||
@ -459,7 +459,7 @@ class chunk_last
|
|||||||
{
|
{
|
||||||
static_assert(
|
static_assert(
|
||||||
is_fields<Trailer>::value ||
|
is_fields<Trailer>::value ||
|
||||||
is_const_buffer_sequence<Trailer>::value,
|
boost::asio::is_const_buffer_sequence<Trailer>::value,
|
||||||
"Trailer requirements not met");
|
"Trailer requirements not met");
|
||||||
|
|
||||||
using buffers_type = typename
|
using buffers_type = typename
|
||||||
|
@ -25,7 +25,7 @@ namespace detail {
|
|||||||
struct chunk_extensions
|
struct chunk_extensions
|
||||||
{
|
{
|
||||||
virtual ~chunk_extensions() = default;
|
virtual ~chunk_extensions() = default;
|
||||||
virtual boost::asio::const_buffers_1 str() = 0;
|
virtual boost::asio::const_buffer str() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class ChunkExtensions>
|
template<class ChunkExtensions>
|
||||||
@ -43,7 +43,7 @@ struct chunk_extensions_impl : chunk_extensions
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::asio::const_buffers_1
|
boost::asio::const_buffer
|
||||||
str() override
|
str() override
|
||||||
{
|
{
|
||||||
auto const s = ext_.str();
|
auto const s = ext_.str();
|
||||||
@ -151,7 +151,7 @@ prepare(std::size_t n)
|
|||||||
|
|
||||||
/// Returns a buffer sequence holding a CRLF for chunk encoding
|
/// Returns a buffer sequence holding a CRLF for chunk encoding
|
||||||
inline
|
inline
|
||||||
boost::asio::const_buffers_1
|
boost::asio::const_buffer
|
||||||
chunk_crlf()
|
chunk_crlf()
|
||||||
{
|
{
|
||||||
return {"\r\n", 2};
|
return {"\r\n", 2};
|
||||||
@ -159,7 +159,7 @@ chunk_crlf()
|
|||||||
|
|
||||||
/// Returns a buffer sequence holding a final chunk header
|
/// Returns a buffer sequence holding a final chunk header
|
||||||
inline
|
inline
|
||||||
boost::asio::const_buffers_1
|
boost::asio::const_buffer
|
||||||
chunk_last()
|
chunk_last()
|
||||||
{
|
{
|
||||||
return {"0\r\n", 3};
|
return {"0\r\n", 3};
|
||||||
|
@ -103,14 +103,13 @@ basic_parser<isRequest, Derived>::
|
|||||||
put(ConstBufferSequence const& buffers,
|
put(ConstBufferSequence const& buffers,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_const_buffer_sequence<
|
static_assert(boost::asio::is_const_buffer_sequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
"ConstBufferSequence requirements not met");
|
"ConstBufferSequence requirements not met");
|
||||||
using boost::asio::buffer_cast;
|
|
||||||
using boost::asio::buffer_copy;
|
using boost::asio::buffer_copy;
|
||||||
using boost::asio::buffer_size;
|
using boost::asio::buffer_size;
|
||||||
auto const p = buffers.begin();
|
auto const p = boost::asio::buffer_sequence_begin(buffers);
|
||||||
auto const last = buffers.end();
|
auto const last = boost::asio::buffer_sequence_end(buffers);
|
||||||
if(p == last)
|
if(p == last)
|
||||||
{
|
{
|
||||||
ec.assign(0, ec.category());
|
ec.assign(0, ec.category());
|
||||||
@ -119,10 +118,7 @@ put(ConstBufferSequence const& buffers,
|
|||||||
if(std::next(p) == last)
|
if(std::next(p) == last)
|
||||||
{
|
{
|
||||||
// single buffer
|
// single buffer
|
||||||
auto const b = *p;
|
return put(boost::asio::const_buffer(*p), ec);
|
||||||
return put(boost::asio::const_buffers_1{
|
|
||||||
buffer_cast<char const*>(b),
|
|
||||||
buffer_size(b)}, ec);
|
|
||||||
}
|
}
|
||||||
auto const size = buffer_size(buffers);
|
auto const size = buffer_size(buffers);
|
||||||
if(size <= max_stack_buffer)
|
if(size <= max_stack_buffer)
|
||||||
@ -136,21 +132,21 @@ put(ConstBufferSequence const& buffers,
|
|||||||
// flatten
|
// flatten
|
||||||
buffer_copy(boost::asio::buffer(
|
buffer_copy(boost::asio::buffer(
|
||||||
buf_.get(), buf_len_), buffers);
|
buf_.get(), buf_len_), buffers);
|
||||||
return put(boost::asio::const_buffers_1{
|
return put(boost::asio::const_buffer{
|
||||||
buf_.get(), buf_len_}, ec);
|
buf_.get(), buf_len_}, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<bool isRequest, class Derived>
|
template<bool isRequest, class Derived>
|
||||||
std::size_t
|
std::size_t
|
||||||
basic_parser<isRequest, Derived>::
|
basic_parser<isRequest, Derived>::
|
||||||
put(boost::asio::const_buffers_1 const& buffer,
|
put(boost::asio::const_buffer const& buffer,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(state_ != state::complete);
|
BOOST_ASSERT(state_ != state::complete);
|
||||||
using boost::asio::buffer_size;
|
using boost::asio::buffer_size;
|
||||||
auto p = boost::asio::buffer_cast<
|
auto p = reinterpret_cast<
|
||||||
char const*>(*buffer.begin());
|
char const*>(buffer.data());
|
||||||
auto n = buffer_size(*buffer.begin());
|
auto n = buffer.size();
|
||||||
auto const p0 = p;
|
auto const p0 = p;
|
||||||
auto const p1 = p0 + n;
|
auto const p1 = p0 + n;
|
||||||
ec.assign(0, ec.category());
|
ec.assign(0, ec.category());
|
||||||
@ -324,7 +320,7 @@ put_from_stack(std::size_t size,
|
|||||||
using boost::asio::buffer;
|
using boost::asio::buffer;
|
||||||
using boost::asio::buffer_copy;
|
using boost::asio::buffer_copy;
|
||||||
buffer_copy(buffer(buf, sizeof(buf)), buffers);
|
buffer_copy(buffer(buf, sizeof(buf)), buffers);
|
||||||
return put(boost::asio::const_buffers_1{
|
return put(boost::asio::const_buffer{
|
||||||
buf, size}, ec);
|
buf, size}, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ chunk_header::
|
|||||||
chunk_header(std::size_t size)
|
chunk_header(std::size_t size)
|
||||||
: view_(
|
: view_(
|
||||||
size,
|
size,
|
||||||
boost::asio::const_buffers_1{nullptr, 0},
|
boost::asio::const_buffer{nullptr, 0},
|
||||||
chunk_crlf{})
|
chunk_crlf{})
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(size > 0);
|
BOOST_ASSERT(size > 0);
|
||||||
@ -37,7 +37,7 @@ chunk_header(
|
|||||||
string_view extensions)
|
string_view extensions)
|
||||||
: view_(
|
: view_(
|
||||||
size,
|
size,
|
||||||
boost::asio::const_buffers_1{
|
boost::asio::const_buffer{
|
||||||
extensions.data(), extensions.size()},
|
extensions.data(), extensions.size()},
|
||||||
chunk_crlf{})
|
chunk_crlf{})
|
||||||
{
|
{
|
||||||
@ -90,7 +90,7 @@ chunk_body<ConstBufferSequence>::
|
|||||||
chunk_body(ConstBufferSequence const& buffers)
|
chunk_body(ConstBufferSequence const& buffers)
|
||||||
: view_(
|
: view_(
|
||||||
boost::asio::buffer_size(buffers),
|
boost::asio::buffer_size(buffers),
|
||||||
boost::asio::const_buffers_1{nullptr, 0},
|
boost::asio::const_buffer{nullptr, 0},
|
||||||
chunk_crlf{},
|
chunk_crlf{},
|
||||||
buffers,
|
buffers,
|
||||||
chunk_crlf{})
|
chunk_crlf{})
|
||||||
@ -104,7 +104,7 @@ chunk_body(
|
|||||||
string_view extensions)
|
string_view extensions)
|
||||||
: view_(
|
: view_(
|
||||||
boost::asio::buffer_size(buffers),
|
boost::asio::buffer_size(buffers),
|
||||||
boost::asio::const_buffers_1{
|
boost::asio::const_buffer{
|
||||||
extensions.data(), extensions.size()},
|
extensions.data(), extensions.size()},
|
||||||
chunk_crlf{},
|
chunk_crlf{},
|
||||||
buffers,
|
buffers,
|
||||||
|
@ -143,9 +143,9 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
using view_type = buffers_cat_view<
|
using view_type = buffers_cat_view<
|
||||||
boost::asio::const_buffers_1,
|
boost::asio::const_buffer,
|
||||||
boost::asio::const_buffers_1,
|
boost::asio::const_buffer,
|
||||||
boost::asio::const_buffers_1,
|
boost::asio::const_buffer,
|
||||||
field_range,
|
field_range,
|
||||||
chunk_crlf>;
|
chunk_crlf>;
|
||||||
|
|
||||||
@ -178,9 +178,9 @@ reader(basic_fields const& f)
|
|||||||
: f_(f)
|
: f_(f)
|
||||||
{
|
{
|
||||||
view_.emplace(
|
view_.emplace(
|
||||||
boost::asio::const_buffers_1{nullptr, 0},
|
boost::asio::const_buffer{nullptr, 0},
|
||||||
boost::asio::const_buffers_1{nullptr, 0},
|
boost::asio::const_buffer{nullptr, 0},
|
||||||
boost::asio::const_buffers_1{nullptr, 0},
|
boost::asio::const_buffer{nullptr, 0},
|
||||||
field_range(f_.list_.begin(), f_.list_.end()),
|
field_range(f_.list_.begin(), f_.list_.end()),
|
||||||
chunk_crlf());
|
chunk_crlf());
|
||||||
}
|
}
|
||||||
@ -218,11 +218,11 @@ reader(basic_fields const& f,
|
|||||||
buf_[10]= '\n';
|
buf_[10]= '\n';
|
||||||
|
|
||||||
view_.emplace(
|
view_.emplace(
|
||||||
boost::asio::const_buffers_1{sv.data(), sv.size()},
|
boost::asio::const_buffer{sv.data(), sv.size()},
|
||||||
boost::asio::const_buffers_1{
|
boost::asio::const_buffer{
|
||||||
f_.target_or_reason_.data(),
|
f_.target_or_reason_.data(),
|
||||||
f_.target_or_reason_.size()},
|
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()),
|
field_range(f_.list_.begin(), f_.list_.end()),
|
||||||
chunk_crlf());
|
chunk_crlf());
|
||||||
}
|
}
|
||||||
@ -260,9 +260,9 @@ reader(basic_fields const& f,
|
|||||||
sv = obsolete_reason(static_cast<status>(code));
|
sv = obsolete_reason(static_cast<status>(code));
|
||||||
|
|
||||||
view_.emplace(
|
view_.emplace(
|
||||||
boost::asio::const_buffers_1{buf_, 13},
|
boost::asio::const_buffer{buf_, 13},
|
||||||
boost::asio::const_buffers_1{sv.data(), sv.size()},
|
boost::asio::const_buffer{sv.data(), sv.size()},
|
||||||
boost::asio::const_buffers_1{"\r\n", 2},
|
boost::asio::const_buffer{"\r\n", 2},
|
||||||
field_range(f_.list_.begin(), f_.list_.end()),
|
field_range(f_.list_.begin(), f_.list_.end()),
|
||||||
chunk_crlf{});
|
chunk_crlf{});
|
||||||
}
|
}
|
||||||
|
@ -12,15 +12,15 @@
|
|||||||
|
|
||||||
#if BOOST_BEAST_USE_WIN32_FILE
|
#if BOOST_BEAST_USE_WIN32_FILE
|
||||||
|
|
||||||
#include <boost/beast/core/async_result.hpp>
|
|
||||||
#include <boost/beast/core/bind_handler.hpp>
|
#include <boost/beast/core/bind_handler.hpp>
|
||||||
#include <boost/beast/core/type_traits.hpp>
|
#include <boost/beast/core/type_traits.hpp>
|
||||||
#include <boost/beast/core/detail/clamp.hpp>
|
#include <boost/beast/core/detail/clamp.hpp>
|
||||||
#include <boost/beast/http/serializer.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/basic_stream_socket.hpp>
|
||||||
#include <boost/asio/handler_alloc_hook.hpp>
|
|
||||||
#include <boost/asio/handler_continuation_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/asio/windows/overlapped_ptr.hpp>
|
||||||
#include <boost/make_unique.hpp>
|
#include <boost/make_unique.hpp>
|
||||||
#include <boost/smart_ptr/make_shared_array.hpp>
|
#include <boost/smart_ptr/make_shared_array.hpp>
|
||||||
@ -120,7 +120,7 @@ struct basic_file_body<file_win32>
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
using const_buffers_type =
|
using const_buffers_type =
|
||||||
boost::asio::const_buffers_1;
|
boost::asio::const_buffer;
|
||||||
|
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
reader(message<isRequest,
|
reader(message<isRequest,
|
||||||
@ -189,12 +189,10 @@ struct basic_file_body<file_win32>
|
|||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
std::size_t nwritten = 0;
|
std::size_t nwritten = 0;
|
||||||
for(boost::asio::const_buffer buffer : buffers)
|
for(auto buffer : beast::detail::buffers_range(buffers))
|
||||||
{
|
{
|
||||||
nwritten += body_.file_.write(
|
nwritten += body_.file_.write(
|
||||||
boost::asio::buffer_cast<void const*>(buffer),
|
buffer.data(), buffer.size(), ec);
|
||||||
boost::asio::buffer_size(buffer),
|
|
||||||
ec);
|
|
||||||
if(ec)
|
if(ec)
|
||||||
return nwritten;
|
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
|
void
|
||||||
operator()();
|
operator()();
|
||||||
|
|
||||||
@ -368,24 +384,6 @@ public:
|
|||||||
error_code ec,
|
error_code ec,
|
||||||
std::size_t bytes_transferred = 0);
|
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
|
friend
|
||||||
bool asio_handler_is_continuation(write_some_win32_op* op)
|
bool asio_handler_is_continuation(write_some_win32_op* op)
|
||||||
{
|
{
|
||||||
@ -393,15 +391,6 @@ public:
|
|||||||
return asio_handler_is_continuation(
|
return asio_handler_is_continuation(
|
||||||
std::addressof(op->h_));
|
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<
|
template<
|
||||||
@ -431,7 +420,7 @@ operator()()
|
|||||||
r.body_.last_ - r.pos_, sr_.limit())),
|
r.body_.last_ - r.pos_, sr_.limit())),
|
||||||
2147483646);
|
2147483646);
|
||||||
boost::asio::windows::overlapped_ptr overlapped{
|
boost::asio::windows::overlapped_ptr overlapped{
|
||||||
sock_.get_io_service(), *this};
|
sock_.get_executor().context(), *this};
|
||||||
auto& ov = *overlapped.get();
|
auto& ov = *overlapped.get();
|
||||||
ov.Offset = lowPart(r.pos_);
|
ov.Offset = lowPart(r.pos_);
|
||||||
ov.OffsetHigh = highPart(r.pos_);
|
ov.OffsetHigh = highPart(r.pos_);
|
||||||
@ -567,21 +556,20 @@ template<
|
|||||||
class Protocol,
|
class Protocol,
|
||||||
bool isRequest, class Fields,
|
bool isRequest, class Fields,
|
||||||
class WriteHandler>
|
class WriteHandler>
|
||||||
async_return_type<
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
WriteHandler,
|
WriteHandler, void(error_code, std::size_t))
|
||||||
void(error_code, std::size_t)>
|
|
||||||
async_write_some(
|
async_write_some(
|
||||||
boost::asio::basic_stream_socket<Protocol>& sock,
|
boost::asio::basic_stream_socket<Protocol>& sock,
|
||||||
serializer<isRequest,
|
serializer<isRequest,
|
||||||
basic_file_body<file_win32>, Fields>& sr,
|
basic_file_body<file_win32>, Fields>& sr,
|
||||||
WriteHandler&& handler)
|
WriteHandler&& handler)
|
||||||
{
|
{
|
||||||
async_completion<WriteHandler,
|
boost::asio::async_completion<WriteHandler,
|
||||||
void(error_code)> init{handler};
|
void(error_code)> init{handler};
|
||||||
detail::write_some_win32_op<
|
detail::write_some_win32_op<
|
||||||
Protocol,
|
Protocol,
|
||||||
handler_type<WriteHandler,
|
BOOST_ASIO_HANDLER_TYPE(WriteHandler,
|
||||||
void(error_code, std::size_t)>,
|
void(error_code, std::size_t)),
|
||||||
isRequest, Fields>{
|
isRequest, Fields>{
|
||||||
init.completion_handler, sock, sr}();
|
init.completion_handler, sock, sr}();
|
||||||
return init.result.get();
|
return init.result.get();
|
||||||
|
@ -18,9 +18,10 @@
|
|||||||
#include <boost/beast/core/handler_ptr.hpp>
|
#include <boost/beast/core/handler_ptr.hpp>
|
||||||
#include <boost/beast/core/read_size.hpp>
|
#include <boost/beast/core/read_size.hpp>
|
||||||
#include <boost/beast/core/type_traits.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_continuation_hook.hpp>
|
||||||
#include <boost/asio/handler_invoke_hook.hpp>
|
#include <boost/asio/post.hpp>
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/config.hpp>
|
#include <boost/config.hpp>
|
||||||
#include <boost/optional.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
|
void
|
||||||
operator()(
|
operator()(
|
||||||
error_code ec = {},
|
error_code ec = {},
|
||||||
std::size_t bytes_transferred = 0);
|
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
|
friend
|
||||||
bool asio_handler_is_continuation(read_some_op* op)
|
bool asio_handler_is_continuation(read_some_op* op)
|
||||||
{
|
{
|
||||||
@ -92,15 +93,6 @@ public:
|
|||||||
asio_handler_is_continuation(
|
asio_handler_is_continuation(
|
||||||
std::addressof(op->h_));
|
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,
|
template<class Stream, class DynamicBuffer,
|
||||||
@ -170,7 +162,8 @@ operator()(
|
|||||||
if(state_ >= 2)
|
if(state_ >= 2)
|
||||||
goto upcall;
|
goto upcall;
|
||||||
state_ = 3;
|
state_ = 3;
|
||||||
return s_.get_io_service().post(
|
return boost::asio::post(
|
||||||
|
s_.get_executor(),
|
||||||
bind_handler(std::move(*this), ec, 0));
|
bind_handler(std::move(*this), ec, 0));
|
||||||
|
|
||||||
case 3:
|
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
|
void
|
||||||
operator()(
|
operator()(
|
||||||
error_code ec = {},
|
error_code ec = {},
|
||||||
std::size_t bytes_transferred = 0);
|
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
|
friend
|
||||||
bool asio_handler_is_continuation(read_op* op)
|
bool asio_handler_is_continuation(read_op* op)
|
||||||
{
|
{
|
||||||
@ -262,15 +255,6 @@ public:
|
|||||||
asio_handler_is_continuation(
|
asio_handler_is_continuation(
|
||||||
std::addressof(op->h_));
|
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,
|
template<class Stream, class DynamicBuffer,
|
||||||
@ -289,7 +273,8 @@ operator()(
|
|||||||
if(Condition{}(p_))
|
if(Condition{}(p_))
|
||||||
{
|
{
|
||||||
state_ = 1;
|
state_ = 1;
|
||||||
return s_.get_io_service().post(
|
return boost::asio::post(
|
||||||
|
s_.get_executor(),
|
||||||
bind_handler(std::move(*this), ec));
|
bind_handler(std::move(*this), ec));
|
||||||
}
|
}
|
||||||
state_ = 2;
|
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
|
void
|
||||||
operator()(
|
operator()(
|
||||||
error_code ec = {},
|
error_code ec = {},
|
||||||
std::size_t bytes_transferred = 0);
|
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
|
friend
|
||||||
bool asio_handler_is_continuation(read_msg_op* op)
|
bool asio_handler_is_continuation(read_msg_op* op)
|
||||||
{
|
{
|
||||||
@ -392,15 +377,6 @@ public:
|
|||||||
asio_handler_is_continuation(
|
asio_handler_is_continuation(
|
||||||
std::addressof(op->d_.handler()));
|
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,
|
template<class Stream, class DynamicBuffer,
|
||||||
@ -458,7 +434,8 @@ read_some(
|
|||||||
{
|
{
|
||||||
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
||||||
"SyncReadStream requirements not met");
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(
|
||||||
|
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
BOOST_ASSERT(! parser.is_done());
|
BOOST_ASSERT(! parser.is_done());
|
||||||
error_code ec;
|
error_code ec;
|
||||||
@ -482,7 +459,8 @@ read_some(
|
|||||||
{
|
{
|
||||||
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
||||||
"SyncReadStream requirements not met");
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(
|
||||||
|
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
BOOST_ASSERT(! parser.is_done());
|
BOOST_ASSERT(! parser.is_done());
|
||||||
std::size_t bytes_transferred = 0;
|
std::size_t bytes_transferred = 0;
|
||||||
@ -541,8 +519,8 @@ template<
|
|||||||
class DynamicBuffer,
|
class DynamicBuffer,
|
||||||
bool isRequest, class Derived,
|
bool isRequest, class Derived,
|
||||||
class ReadHandler>
|
class ReadHandler>
|
||||||
async_return_type<
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
ReadHandler, void(error_code, std::size_t)>
|
ReadHandler, void(error_code, std::size_t))
|
||||||
async_read_some(
|
async_read_some(
|
||||||
AsyncReadStream& stream,
|
AsyncReadStream& stream,
|
||||||
DynamicBuffer& buffer,
|
DynamicBuffer& buffer,
|
||||||
@ -551,13 +529,14 @@ async_read_some(
|
|||||||
{
|
{
|
||||||
static_assert(is_async_read_stream<AsyncReadStream>::value,
|
static_assert(is_async_read_stream<AsyncReadStream>::value,
|
||||||
"AsyncReadStream requirements not met");
|
"AsyncReadStream requirements not met");
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(
|
||||||
|
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
BOOST_ASSERT(! parser.is_done());
|
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,
|
detail::read_some_op<AsyncReadStream,
|
||||||
DynamicBuffer, isRequest, Derived, handler_type<
|
DynamicBuffer, isRequest, Derived, BOOST_ASIO_HANDLER_TYPE(
|
||||||
ReadHandler, void(error_code, std::size_t)>>{
|
ReadHandler, void(error_code, std::size_t))>{
|
||||||
init.completion_handler, stream, buffer, parser}();
|
init.completion_handler, stream, buffer, parser}();
|
||||||
return init.result.get();
|
return init.result.get();
|
||||||
}
|
}
|
||||||
@ -576,7 +555,8 @@ read_header(
|
|||||||
{
|
{
|
||||||
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
||||||
"SyncReadStream requirements not met");
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(
|
||||||
|
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
error_code ec;
|
error_code ec;
|
||||||
auto const bytes_transferred =
|
auto const bytes_transferred =
|
||||||
@ -599,7 +579,8 @@ read_header(
|
|||||||
{
|
{
|
||||||
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
||||||
"SyncReadStream requirements not met");
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(
|
||||||
|
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
parser.eager(false);
|
parser.eager(false);
|
||||||
if(parser.is_header_done())
|
if(parser.is_header_done())
|
||||||
@ -624,9 +605,8 @@ template<
|
|||||||
class DynamicBuffer,
|
class DynamicBuffer,
|
||||||
bool isRequest, class Derived,
|
bool isRequest, class Derived,
|
||||||
class ReadHandler>
|
class ReadHandler>
|
||||||
async_return_type<
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
ReadHandler,
|
ReadHandler, void(error_code, std::size_t))
|
||||||
void(error_code, std::size_t)>
|
|
||||||
async_read_header(
|
async_read_header(
|
||||||
AsyncReadStream& stream,
|
AsyncReadStream& stream,
|
||||||
DynamicBuffer& buffer,
|
DynamicBuffer& buffer,
|
||||||
@ -635,14 +615,15 @@ async_read_header(
|
|||||||
{
|
{
|
||||||
static_assert(is_async_read_stream<AsyncReadStream>::value,
|
static_assert(is_async_read_stream<AsyncReadStream>::value,
|
||||||
"AsyncReadStream requirements not met");
|
"AsyncReadStream requirements not met");
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(
|
||||||
|
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
parser.eager(false);
|
parser.eager(false);
|
||||||
async_completion<ReadHandler,
|
boost::asio::async_completion<ReadHandler,
|
||||||
void(error_code, std::size_t)> init{handler};
|
void(error_code, std::size_t)> init{handler};
|
||||||
detail::read_op<AsyncReadStream, DynamicBuffer,
|
detail::read_op<AsyncReadStream, DynamicBuffer,
|
||||||
isRequest, Derived, detail::parser_is_header_done,
|
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}();
|
init.completion_handler, stream, buffer, parser}();
|
||||||
return init.result.get();
|
return init.result.get();
|
||||||
}
|
}
|
||||||
@ -661,7 +642,8 @@ read(
|
|||||||
{
|
{
|
||||||
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
||||||
"SyncReadStream requirements not met");
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(
|
||||||
|
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
error_code ec;
|
error_code ec;
|
||||||
auto const bytes_transferred =
|
auto const bytes_transferred =
|
||||||
@ -684,7 +666,8 @@ read(
|
|||||||
{
|
{
|
||||||
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
||||||
"SyncReadStream requirements not met");
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(
|
||||||
|
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
parser.eager(true);
|
parser.eager(true);
|
||||||
if(parser.is_done())
|
if(parser.is_done())
|
||||||
@ -709,9 +692,8 @@ template<
|
|||||||
class DynamicBuffer,
|
class DynamicBuffer,
|
||||||
bool isRequest, class Derived,
|
bool isRequest, class Derived,
|
||||||
class ReadHandler>
|
class ReadHandler>
|
||||||
async_return_type<
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
ReadHandler,
|
ReadHandler, void(error_code, std::size_t))
|
||||||
void(error_code, std::size_t)>
|
|
||||||
async_read(
|
async_read(
|
||||||
AsyncReadStream& stream,
|
AsyncReadStream& stream,
|
||||||
DynamicBuffer& buffer,
|
DynamicBuffer& buffer,
|
||||||
@ -720,15 +702,16 @@ async_read(
|
|||||||
{
|
{
|
||||||
static_assert(is_async_read_stream<AsyncReadStream>::value,
|
static_assert(is_async_read_stream<AsyncReadStream>::value,
|
||||||
"AsyncReadStream requirements not met");
|
"AsyncReadStream requirements not met");
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(
|
||||||
|
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
parser.eager(true);
|
parser.eager(true);
|
||||||
async_completion<
|
boost::asio::async_completion<
|
||||||
ReadHandler,
|
ReadHandler,
|
||||||
void(error_code, std::size_t)> init{handler};
|
void(error_code, std::size_t)> init{handler};
|
||||||
detail::read_op<AsyncReadStream, DynamicBuffer,
|
detail::read_op<AsyncReadStream, DynamicBuffer,
|
||||||
isRequest, Derived, detail::parser_is_done,
|
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}();
|
init.completion_handler, stream, buffer, parser}();
|
||||||
return init.result.get();
|
return init.result.get();
|
||||||
}
|
}
|
||||||
@ -747,7 +730,8 @@ read(
|
|||||||
{
|
{
|
||||||
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
||||||
"SyncReadStream requirements not met");
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(
|
||||||
|
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
static_assert(is_body<Body>::value,
|
static_assert(is_body<Body>::value,
|
||||||
"Body requirements not met");
|
"Body requirements not met");
|
||||||
@ -774,7 +758,8 @@ read(
|
|||||||
{
|
{
|
||||||
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
||||||
"SyncReadStream requirements not met");
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(
|
||||||
|
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
static_assert(is_body<Body>::value,
|
static_assert(is_body<Body>::value,
|
||||||
"Body requirements not met");
|
"Body requirements not met");
|
||||||
@ -795,9 +780,8 @@ template<
|
|||||||
class DynamicBuffer,
|
class DynamicBuffer,
|
||||||
bool isRequest, class Body, class Allocator,
|
bool isRequest, class Body, class Allocator,
|
||||||
class ReadHandler>
|
class ReadHandler>
|
||||||
async_return_type<
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
ReadHandler,
|
ReadHandler, void(error_code, std::size_t))
|
||||||
void(error_code, std::size_t)>
|
|
||||||
async_read(
|
async_read(
|
||||||
AsyncReadStream& stream,
|
AsyncReadStream& stream,
|
||||||
DynamicBuffer& buffer,
|
DynamicBuffer& buffer,
|
||||||
@ -806,21 +790,22 @@ async_read(
|
|||||||
{
|
{
|
||||||
static_assert(is_async_read_stream<AsyncReadStream>::value,
|
static_assert(is_async_read_stream<AsyncReadStream>::value,
|
||||||
"AsyncReadStream requirements not met");
|
"AsyncReadStream requirements not met");
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(
|
||||||
|
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
static_assert(is_body<Body>::value,
|
static_assert(is_body<Body>::value,
|
||||||
"Body requirements not met");
|
"Body requirements not met");
|
||||||
static_assert(is_body_writer<Body>::value,
|
static_assert(is_body_writer<Body>::value,
|
||||||
"BodyWriter requirements not met");
|
"BodyWriter requirements not met");
|
||||||
async_completion<
|
boost::asio::async_completion<
|
||||||
ReadHandler,
|
ReadHandler,
|
||||||
void(error_code, std::size_t)> init{handler};
|
void(error_code, std::size_t)> init{handler};
|
||||||
detail::read_msg_op<
|
detail::read_msg_op<
|
||||||
AsyncReadStream,
|
AsyncReadStream,
|
||||||
DynamicBuffer,
|
DynamicBuffer,
|
||||||
isRequest, Body, Allocator,
|
isRequest, Body, Allocator,
|
||||||
handler_type<ReadHandler,
|
BOOST_ASIO_HANDLER_TYPE(
|
||||||
void(error_code, std::size_t)>>{
|
ReadHandler, void(error_code, std::size_t))>{
|
||||||
init.completion_handler, stream, buffer, msg}();
|
init.completion_handler, stream, buffer, msg}();
|
||||||
return init.result.get();
|
return init.result.get();
|
||||||
}
|
}
|
||||||
|
@ -166,12 +166,12 @@ next(error_code& ec, Visit&& visit)
|
|||||||
boost::in_place_init,
|
boost::in_place_init,
|
||||||
frd_->get(),
|
frd_->get(),
|
||||||
buffer_size(result->first),
|
buffer_size(result->first),
|
||||||
boost::asio::const_buffers_1{nullptr, 0},
|
boost::asio::const_buffer{nullptr, 0},
|
||||||
chunk_crlf{},
|
chunk_crlf{},
|
||||||
result->first,
|
result->first,
|
||||||
chunk_crlf{},
|
chunk_crlf{},
|
||||||
detail::chunk_last(),
|
detail::chunk_last(),
|
||||||
boost::asio::const_buffers_1{nullptr, 0},
|
boost::asio::const_buffer{nullptr, 0},
|
||||||
chunk_crlf{});
|
chunk_crlf{});
|
||||||
goto go_all_c;
|
goto go_all_c;
|
||||||
}
|
}
|
||||||
@ -179,7 +179,7 @@ next(error_code& ec, Visit&& visit)
|
|||||||
boost::in_place_init,
|
boost::in_place_init,
|
||||||
frd_->get(),
|
frd_->get(),
|
||||||
buffer_size(result->first),
|
buffer_size(result->first),
|
||||||
boost::asio::const_buffers_1{nullptr, 0},
|
boost::asio::const_buffer{nullptr, 0},
|
||||||
chunk_crlf{},
|
chunk_crlf{},
|
||||||
result->first,
|
result->first,
|
||||||
chunk_crlf{});
|
chunk_crlf{});
|
||||||
@ -216,19 +216,19 @@ next(error_code& ec, Visit&& visit)
|
|||||||
v_.template emplace<6>(
|
v_.template emplace<6>(
|
||||||
boost::in_place_init,
|
boost::in_place_init,
|
||||||
buffer_size(result->first),
|
buffer_size(result->first),
|
||||||
boost::asio::const_buffers_1{nullptr, 0},
|
boost::asio::const_buffer{nullptr, 0},
|
||||||
chunk_crlf{},
|
chunk_crlf{},
|
||||||
result->first,
|
result->first,
|
||||||
chunk_crlf{},
|
chunk_crlf{},
|
||||||
detail::chunk_last(),
|
detail::chunk_last(),
|
||||||
boost::asio::const_buffers_1{nullptr, 0},
|
boost::asio::const_buffer{nullptr, 0},
|
||||||
chunk_crlf{});
|
chunk_crlf{});
|
||||||
goto go_body_final_c;
|
goto go_body_final_c;
|
||||||
}
|
}
|
||||||
v_.template emplace<5>(
|
v_.template emplace<5>(
|
||||||
boost::in_place_init,
|
boost::in_place_init,
|
||||||
buffer_size(result->first),
|
buffer_size(result->first),
|
||||||
boost::asio::const_buffers_1{nullptr, 0},
|
boost::asio::const_buffer{nullptr, 0},
|
||||||
chunk_crlf{},
|
chunk_crlf{},
|
||||||
result->first,
|
result->first,
|
||||||
chunk_crlf{});
|
chunk_crlf{});
|
||||||
@ -257,7 +257,7 @@ next(error_code& ec, Visit&& visit)
|
|||||||
v_.template emplace<8>(
|
v_.template emplace<8>(
|
||||||
boost::in_place_init,
|
boost::in_place_init,
|
||||||
detail::chunk_last(),
|
detail::chunk_last(),
|
||||||
boost::asio::const_buffers_1{nullptr, 0},
|
boost::asio::const_buffer{nullptr, 0},
|
||||||
chunk_crlf{});
|
chunk_crlf{});
|
||||||
s_ = do_final_c + 1;
|
s_ = do_final_c + 1;
|
||||||
BOOST_BEAST_FALLTHROUGH;
|
BOOST_BEAST_FALLTHROUGH;
|
||||||
|
@ -16,9 +16,10 @@
|
|||||||
#include <boost/beast/core/handler_ptr.hpp>
|
#include <boost/beast/core/handler_ptr.hpp>
|
||||||
#include <boost/beast/core/type_traits.hpp>
|
#include <boost/beast/core/type_traits.hpp>
|
||||||
#include <boost/beast/core/detail/config.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_continuation_hook.hpp>
|
||||||
#include <boost/asio/handler_invoke_hook.hpp>
|
#include <boost/asio/post.hpp>
|
||||||
#include <boost/asio/write.hpp>
|
#include <boost/asio/write.hpp>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
#include <boost/throw_exception.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
|
void
|
||||||
operator()();
|
operator()();
|
||||||
|
|
||||||
@ -85,24 +104,6 @@ public:
|
|||||||
error_code ec,
|
error_code ec,
|
||||||
std::size_t bytes_transferred);
|
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
|
friend
|
||||||
bool asio_handler_is_continuation(write_some_op* op)
|
bool asio_handler_is_continuation(write_some_op* op)
|
||||||
{
|
{
|
||||||
@ -110,14 +111,6 @@ public:
|
|||||||
return asio_handler_is_continuation(
|
return asio_handler_is_continuation(
|
||||||
std::addressof(op->h_));
|
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<
|
template<
|
||||||
@ -136,7 +129,8 @@ operator()()
|
|||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(! f.invoked);
|
BOOST_ASSERT(! f.invoked);
|
||||||
return s_.get_io_service().post(
|
return boost::asio::post(
|
||||||
|
s_.get_executor(),
|
||||||
bind_handler(std::move(*this), ec, 0));
|
bind_handler(std::move(*this), ec, 0));
|
||||||
}
|
}
|
||||||
if(f.invoked)
|
if(f.invoked)
|
||||||
@ -148,7 +142,8 @@ operator()()
|
|||||||
// What else could it be?
|
// What else could it be?
|
||||||
BOOST_ASSERT(sr_.is_done());
|
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));
|
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
|
void
|
||||||
operator()(
|
operator()(
|
||||||
error_code ec = {},
|
error_code ec = {},
|
||||||
std::size_t bytes_transferred = 0);
|
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
|
friend
|
||||||
bool asio_handler_is_continuation(write_op* op)
|
bool asio_handler_is_continuation(write_op* op)
|
||||||
{
|
{
|
||||||
@ -249,15 +244,6 @@ public:
|
|||||||
asio_handler_is_continuation(
|
asio_handler_is_continuation(
|
||||||
std::addressof(op->h_));
|
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<
|
template<
|
||||||
@ -278,7 +264,8 @@ operator()(
|
|||||||
if(Predicate{}(sr_))
|
if(Predicate{}(sr_))
|
||||||
{
|
{
|
||||||
state_ = 1;
|
state_ = 1;
|
||||||
return s_.get_io_service().post(
|
return boost::asio::post(
|
||||||
|
s_.get_executor(),
|
||||||
bind_handler(std::move(*this), ec, 0));
|
bind_handler(std::move(*this), ec, 0));
|
||||||
}
|
}
|
||||||
state_ = 2;
|
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
|
void
|
||||||
operator()();
|
operator()();
|
||||||
|
|
||||||
@ -345,24 +350,6 @@ public:
|
|||||||
operator()(
|
operator()(
|
||||||
error_code ec, std::size_t bytes_transferred);
|
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
|
friend
|
||||||
bool asio_handler_is_continuation(write_msg_op* op)
|
bool asio_handler_is_continuation(write_msg_op* op)
|
||||||
{
|
{
|
||||||
@ -370,15 +357,6 @@ public:
|
|||||||
return asio_handler_is_continuation(
|
return asio_handler_is_continuation(
|
||||||
std::addressof(op->d_.handler()));
|
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,
|
template<class Stream, class Handler,
|
||||||
@ -483,21 +461,20 @@ template<
|
|||||||
class AsyncWriteStream,
|
class AsyncWriteStream,
|
||||||
bool isRequest, class Body, class Fields,
|
bool isRequest, class Body, class Fields,
|
||||||
class WriteHandler>
|
class WriteHandler>
|
||||||
async_return_type<
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
WriteHandler,
|
WriteHandler, void(error_code, std::size_t))
|
||||||
void(error_code, std::size_t)>
|
|
||||||
async_write_some(
|
async_write_some(
|
||||||
AsyncWriteStream& stream,
|
AsyncWriteStream& stream,
|
||||||
serializer<isRequest, Body, Fields>& sr,
|
serializer<isRequest, Body, Fields>& sr,
|
||||||
WriteHandler&& handler)
|
WriteHandler&& handler)
|
||||||
{
|
{
|
||||||
async_completion<
|
boost::asio::async_completion<
|
||||||
WriteHandler,
|
WriteHandler,
|
||||||
void(error_code, std::size_t)> init{handler};
|
void(error_code, std::size_t)> init{handler};
|
||||||
detail::write_some_op<
|
detail::write_some_op<
|
||||||
AsyncWriteStream,
|
AsyncWriteStream,
|
||||||
handler_type<WriteHandler,
|
BOOST_ASIO_HANDLER_TYPE(WriteHandler,
|
||||||
void(error_code, std::size_t)>,
|
void(error_code, std::size_t)),
|
||||||
isRequest, Body, Fields>{
|
isRequest, Body, Fields>{
|
||||||
init.completion_handler, stream, sr}();
|
init.completion_handler, stream, sr}();
|
||||||
return init.result.get();
|
return init.result.get();
|
||||||
@ -551,9 +528,8 @@ template<
|
|||||||
class AsyncWriteStream,
|
class AsyncWriteStream,
|
||||||
bool isRequest, class Body, class Fields,
|
bool isRequest, class Body, class Fields,
|
||||||
class WriteHandler>
|
class WriteHandler>
|
||||||
async_return_type<
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
WriteHandler,
|
WriteHandler, void(error_code, std::size_t))
|
||||||
void(error_code, std::size_t)>
|
|
||||||
async_write_some(
|
async_write_some(
|
||||||
AsyncWriteStream& stream,
|
AsyncWriteStream& stream,
|
||||||
serializer<isRequest, Body, Fields>& sr,
|
serializer<isRequest, Body, Fields>& sr,
|
||||||
@ -635,9 +611,8 @@ template<
|
|||||||
class AsyncWriteStream,
|
class AsyncWriteStream,
|
||||||
bool isRequest, class Body, class Fields,
|
bool isRequest, class Body, class Fields,
|
||||||
class WriteHandler>
|
class WriteHandler>
|
||||||
async_return_type<
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
WriteHandler,
|
WriteHandler, void(error_code, std::size_t))
|
||||||
void(error_code, std::size_t)>
|
|
||||||
async_write_header(
|
async_write_header(
|
||||||
AsyncWriteStream& stream,
|
AsyncWriteStream& stream,
|
||||||
serializer<isRequest, Body, Fields>& sr,
|
serializer<isRequest, Body, Fields>& sr,
|
||||||
@ -651,13 +626,13 @@ async_write_header(
|
|||||||
static_assert(is_body_reader<Body>::value,
|
static_assert(is_body_reader<Body>::value,
|
||||||
"BodyReader requirements not met");
|
"BodyReader requirements not met");
|
||||||
sr.split(true);
|
sr.split(true);
|
||||||
async_completion<
|
boost::asio::async_completion<
|
||||||
WriteHandler,
|
WriteHandler,
|
||||||
void(error_code, std::size_t)> init{handler};
|
void(error_code, std::size_t)> init{handler};
|
||||||
detail::write_op<
|
detail::write_op<
|
||||||
AsyncWriteStream,
|
AsyncWriteStream,
|
||||||
handler_type<WriteHandler,
|
BOOST_ASIO_HANDLER_TYPE(WriteHandler,
|
||||||
void(error_code, std::size_t)>,
|
void(error_code, std::size_t)),
|
||||||
detail::serializer_is_header_done,
|
detail::serializer_is_header_done,
|
||||||
isRequest, Body, Fields>{
|
isRequest, Body, Fields>{
|
||||||
init.completion_handler, stream, sr}();
|
init.completion_handler, stream, sr}();
|
||||||
@ -713,9 +688,8 @@ template<
|
|||||||
class AsyncWriteStream,
|
class AsyncWriteStream,
|
||||||
bool isRequest, class Body, class Fields,
|
bool isRequest, class Body, class Fields,
|
||||||
class WriteHandler>
|
class WriteHandler>
|
||||||
async_return_type<
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
WriteHandler,
|
WriteHandler, void(error_code, std::size_t))
|
||||||
void(error_code, std::size_t)>
|
|
||||||
async_write(
|
async_write(
|
||||||
AsyncWriteStream& stream,
|
AsyncWriteStream& stream,
|
||||||
serializer<isRequest, Body, Fields>& sr,
|
serializer<isRequest, Body, Fields>& sr,
|
||||||
@ -729,13 +703,13 @@ async_write(
|
|||||||
static_assert(is_body_reader<Body>::value,
|
static_assert(is_body_reader<Body>::value,
|
||||||
"BodyReader requirements not met");
|
"BodyReader requirements not met");
|
||||||
sr.split(false);
|
sr.split(false);
|
||||||
async_completion<
|
boost::asio::async_completion<
|
||||||
WriteHandler,
|
WriteHandler,
|
||||||
void(error_code, std::size_t)> init{handler};
|
void(error_code, std::size_t)> init{handler};
|
||||||
detail::write_op<
|
detail::write_op<
|
||||||
AsyncWriteStream,
|
AsyncWriteStream,
|
||||||
handler_type<WriteHandler,
|
BOOST_ASIO_HANDLER_TYPE(WriteHandler,
|
||||||
void(error_code, std::size_t)>,
|
void(error_code, std::size_t)),
|
||||||
detail::serializer_is_done,
|
detail::serializer_is_done,
|
||||||
isRequest, Body, Fields>{
|
isRequest, Body, Fields>{
|
||||||
init.completion_handler, stream, sr}();
|
init.completion_handler, stream, sr}();
|
||||||
@ -789,9 +763,8 @@ template<
|
|||||||
class AsyncWriteStream,
|
class AsyncWriteStream,
|
||||||
bool isRequest, class Body, class Fields,
|
bool isRequest, class Body, class Fields,
|
||||||
class WriteHandler>
|
class WriteHandler>
|
||||||
async_return_type<
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
WriteHandler,
|
WriteHandler, void(error_code, std::size_t))
|
||||||
void(error_code, std::size_t)>
|
|
||||||
async_write(
|
async_write(
|
||||||
AsyncWriteStream& stream,
|
AsyncWriteStream& stream,
|
||||||
message<isRequest, Body, Fields>& msg,
|
message<isRequest, Body, Fields>& msg,
|
||||||
@ -804,13 +777,13 @@ async_write(
|
|||||||
"Body requirements not met");
|
"Body requirements not met");
|
||||||
static_assert(is_body_reader<Body>::value,
|
static_assert(is_body_reader<Body>::value,
|
||||||
"BodyReader requirements not met");
|
"BodyReader requirements not met");
|
||||||
async_completion<
|
boost::asio::async_completion<
|
||||||
WriteHandler,
|
WriteHandler,
|
||||||
void(error_code, std::size_t)> init{handler};
|
void(error_code, std::size_t)> init{handler};
|
||||||
detail::write_msg_op<
|
detail::write_msg_op<
|
||||||
AsyncWriteStream,
|
AsyncWriteStream,
|
||||||
handler_type<WriteHandler,
|
BOOST_ASIO_HANDLER_TYPE(WriteHandler,
|
||||||
void(error_code, std::size_t)>,
|
void(error_code, std::size_t)),
|
||||||
isRequest, Body, Fields>{
|
isRequest, Body, Fields>{
|
||||||
init.completion_handler, stream, msg}();
|
init.completion_handler, stream, msg}();
|
||||||
return init.result.get();
|
return init.result.get();
|
||||||
@ -843,17 +816,13 @@ public:
|
|||||||
if(os_.fail())
|
if(os_.fail())
|
||||||
return;
|
return;
|
||||||
std::size_t bytes_transferred = 0;
|
std::size_t bytes_transferred = 0;
|
||||||
using boost::asio::buffer_cast;
|
for(auto b : buffers_range(buffers))
|
||||||
using boost::asio::buffer_size;
|
|
||||||
for(auto it = buffers.begin();
|
|
||||||
it != buffers.end(); ++it)
|
|
||||||
{
|
{
|
||||||
boost::asio::const_buffer b = *it;
|
os_.write(reinterpret_cast<char const*>(
|
||||||
auto const n = buffer_size(b);
|
b.data()), b.size());
|
||||||
os_.write(buffer_cast<char const*>(b), n);
|
|
||||||
if(os_.fail())
|
if(os_.fail())
|
||||||
return;
|
return;
|
||||||
bytes_transferred += n;
|
bytes_transferred += b.size();
|
||||||
}
|
}
|
||||||
sr_.consume(bytes_transferred);
|
sr_.consume(bytes_transferred);
|
||||||
}
|
}
|
||||||
|
@ -11,10 +11,10 @@
|
|||||||
#define BOOST_BEAST_HTTP_READ_HPP
|
#define BOOST_BEAST_HTTP_READ_HPP
|
||||||
|
|
||||||
#include <boost/beast/core/detail/config.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/error.hpp>
|
||||||
#include <boost/beast/http/basic_parser.hpp>
|
#include <boost/beast/http/basic_parser.hpp>
|
||||||
#include <boost/beast/http/message.hpp>
|
#include <boost/beast/http/message.hpp>
|
||||||
|
#include <boost/asio/async_result.hpp>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
namespace beast {
|
namespace beast {
|
||||||
@ -185,7 +185,7 @@ read_some(
|
|||||||
Regardless of whether the asynchronous operation completes
|
Regardless of whether the asynchronous operation completes
|
||||||
immediately or not, the handler will not be invoked from within
|
immediately or not, the handler will not be invoked from within
|
||||||
this function. Invocation of the handler will be performed in a
|
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
|
The completion handler will receive as a parameter the number
|
||||||
of octets processed from the dynamic buffer. The octets should
|
of octets processed from the dynamic buffer. The octets should
|
||||||
@ -197,12 +197,8 @@ template<
|
|||||||
class DynamicBuffer,
|
class DynamicBuffer,
|
||||||
bool isRequest, class Derived,
|
bool isRequest, class Derived,
|
||||||
class ReadHandler>
|
class ReadHandler>
|
||||||
#if BOOST_BEAST_DOXYGEN
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
void_or_deduced
|
ReadHandler, void(error_code, std::size_t))
|
||||||
#else
|
|
||||||
async_return_type<
|
|
||||||
ReadHandler, void(error_code, std::size_t)>
|
|
||||||
#endif
|
|
||||||
async_read_some(
|
async_read_some(
|
||||||
AsyncReadStream& stream,
|
AsyncReadStream& stream,
|
||||||
DynamicBuffer& buffer,
|
DynamicBuffer& buffer,
|
||||||
@ -375,7 +371,7 @@ read_header(
|
|||||||
Regardless of whether the asynchronous operation completes
|
Regardless of whether the asynchronous operation completes
|
||||||
immediately or not, the handler will not be invoked from within
|
immediately or not, the handler will not be invoked from within
|
||||||
this function. Invocation of the handler will be performed in a
|
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
|
@note The implementation will call @ref basic_parser::eager
|
||||||
with the value `false` on the parser passed in.
|
with the value `false` on the parser passed in.
|
||||||
@ -385,12 +381,8 @@ template<
|
|||||||
class DynamicBuffer,
|
class DynamicBuffer,
|
||||||
bool isRequest, class Derived,
|
bool isRequest, class Derived,
|
||||||
class ReadHandler>
|
class ReadHandler>
|
||||||
#if BOOST_BEAST_DOXYGEN
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
void_or_deduced
|
ReadHandler, void(error_code, std::size_t))
|
||||||
#else
|
|
||||||
async_return_type<
|
|
||||||
ReadHandler, void(error_code, std::size_t)>
|
|
||||||
#endif
|
|
||||||
async_read_header(
|
async_read_header(
|
||||||
AsyncReadStream& stream,
|
AsyncReadStream& stream,
|
||||||
DynamicBuffer& buffer,
|
DynamicBuffer& buffer,
|
||||||
@ -563,7 +555,7 @@ read(
|
|||||||
Regardless of whether the asynchronous operation completes
|
Regardless of whether the asynchronous operation completes
|
||||||
immediately or not, the handler will not be invoked from within
|
immediately or not, the handler will not be invoked from within
|
||||||
this function. Invocation of the handler will be performed in a
|
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
|
@note The implementation will call @ref basic_parser::eager
|
||||||
with the value `true` on the parser passed in.
|
with the value `true` on the parser passed in.
|
||||||
@ -573,13 +565,8 @@ template<
|
|||||||
class DynamicBuffer,
|
class DynamicBuffer,
|
||||||
bool isRequest, class Derived,
|
bool isRequest, class Derived,
|
||||||
class ReadHandler>
|
class ReadHandler>
|
||||||
#if BOOST_BEAST_DOXYGEN
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
void_or_deduced
|
ReadHandler, void(error_code, std::size_t))
|
||||||
#else
|
|
||||||
async_return_type<
|
|
||||||
ReadHandler,
|
|
||||||
void(error_code, std::size_t)>
|
|
||||||
#endif
|
|
||||||
async_read(
|
async_read(
|
||||||
AsyncReadStream& stream,
|
AsyncReadStream& stream,
|
||||||
DynamicBuffer& buffer,
|
DynamicBuffer& buffer,
|
||||||
@ -754,20 +741,15 @@ read(
|
|||||||
Regardless of whether the asynchronous operation completes
|
Regardless of whether the asynchronous operation completes
|
||||||
immediately or not, the handler will not be invoked from within
|
immediately or not, the handler will not be invoked from within
|
||||||
this function. Invocation of the handler will be performed in a
|
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<
|
template<
|
||||||
class AsyncReadStream,
|
class AsyncReadStream,
|
||||||
class DynamicBuffer,
|
class DynamicBuffer,
|
||||||
bool isRequest, class Body, class Allocator,
|
bool isRequest, class Body, class Allocator,
|
||||||
class ReadHandler>
|
class ReadHandler>
|
||||||
#if BOOST_BEAST_DOXYGEN
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
void_or_deduced
|
ReadHandler, void(error_code, std::size_t))
|
||||||
#else
|
|
||||||
async_return_type<
|
|
||||||
ReadHandler,
|
|
||||||
void(error_code, std::size_t)>
|
|
||||||
#endif
|
|
||||||
async_read(
|
async_read(
|
||||||
AsyncReadStream& stream,
|
AsyncReadStream& stream,
|
||||||
DynamicBuffer& buffer,
|
DynamicBuffer& buffer,
|
||||||
|
@ -132,7 +132,7 @@ private:
|
|||||||
using cb4_t = buffers_suffix<buffers_cat_view<
|
using cb4_t = buffers_suffix<buffers_cat_view<
|
||||||
typename Fields::reader::const_buffers_type,// header
|
typename Fields::reader::const_buffers_type,// header
|
||||||
detail::chunk_size, // chunk-size
|
detail::chunk_size, // chunk-size
|
||||||
boost::asio::const_buffers_1, // chunk-ext
|
boost::asio::const_buffer, // chunk-ext
|
||||||
chunk_crlf, // crlf
|
chunk_crlf, // crlf
|
||||||
typename reader::const_buffers_type, // body
|
typename reader::const_buffers_type, // body
|
||||||
chunk_crlf>>; // crlf
|
chunk_crlf>>; // crlf
|
||||||
@ -140,7 +140,7 @@ private:
|
|||||||
|
|
||||||
using cb5_t = buffers_suffix<buffers_cat_view<
|
using cb5_t = buffers_suffix<buffers_cat_view<
|
||||||
detail::chunk_size, // chunk-header
|
detail::chunk_size, // chunk-header
|
||||||
boost::asio::const_buffers_1, // chunk-ext
|
boost::asio::const_buffer, // chunk-ext
|
||||||
chunk_crlf, // crlf
|
chunk_crlf, // crlf
|
||||||
typename reader::const_buffers_type, // body
|
typename reader::const_buffers_type, // body
|
||||||
chunk_crlf>>; // crlf
|
chunk_crlf>>; // crlf
|
||||||
@ -148,30 +148,30 @@ private:
|
|||||||
|
|
||||||
using cb6_t = buffers_suffix<buffers_cat_view<
|
using cb6_t = buffers_suffix<buffers_cat_view<
|
||||||
detail::chunk_size, // chunk-header
|
detail::chunk_size, // chunk-header
|
||||||
boost::asio::const_buffers_1, // chunk-size
|
boost::asio::const_buffer, // chunk-size
|
||||||
chunk_crlf, // crlf
|
chunk_crlf, // crlf
|
||||||
typename reader::const_buffers_type, // body
|
typename reader::const_buffers_type, // body
|
||||||
chunk_crlf, // crlf
|
chunk_crlf, // crlf
|
||||||
boost::asio::const_buffers_1, // chunk-final
|
boost::asio::const_buffer, // chunk-final
|
||||||
boost::asio::const_buffers_1, // trailers
|
boost::asio::const_buffer, // trailers
|
||||||
chunk_crlf>>; // crlf
|
chunk_crlf>>; // crlf
|
||||||
using pcb6_t = buffers_prefix_view<cb6_t const&>;
|
using pcb6_t = buffers_prefix_view<cb6_t const&>;
|
||||||
|
|
||||||
using cb7_t = buffers_suffix<buffers_cat_view<
|
using cb7_t = buffers_suffix<buffers_cat_view<
|
||||||
typename Fields::reader::const_buffers_type,// header
|
typename Fields::reader::const_buffers_type,// header
|
||||||
detail::chunk_size, // chunk-size
|
detail::chunk_size, // chunk-size
|
||||||
boost::asio::const_buffers_1, // chunk-ext
|
boost::asio::const_buffer, // chunk-ext
|
||||||
chunk_crlf, // crlf
|
chunk_crlf, // crlf
|
||||||
typename reader::const_buffers_type, // body
|
typename reader::const_buffers_type, // body
|
||||||
chunk_crlf, // crlf
|
chunk_crlf, // crlf
|
||||||
boost::asio::const_buffers_1, // chunk-final
|
boost::asio::const_buffer, // chunk-final
|
||||||
boost::asio::const_buffers_1, // trailers
|
boost::asio::const_buffer, // trailers
|
||||||
chunk_crlf>>; // crlf
|
chunk_crlf>>; // crlf
|
||||||
using pcb7_t = buffers_prefix_view<cb7_t const&>;
|
using pcb7_t = buffers_prefix_view<cb7_t const&>;
|
||||||
|
|
||||||
using cb8_t = buffers_suffix<buffers_cat_view<
|
using cb8_t = buffers_suffix<buffers_cat_view<
|
||||||
boost::asio::const_buffers_1, // chunk-final
|
boost::asio::const_buffer, // chunk-final
|
||||||
boost::asio::const_buffers_1, // trailers
|
boost::asio::const_buffer, // trailers
|
||||||
chunk_crlf>>; // crlf
|
chunk_crlf>>; // crlf
|
||||||
using pcb8_t = buffers_prefix_view<cb8_t const&>;
|
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