Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:27

0001 //
0002 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // Official repository: https://github.com/boostorg/beast
0008 //
0009 
0010 #ifndef BOOST_BEAST_CORE_BASIC_STREAM_HPP
0011 #define BOOST_BEAST_CORE_BASIC_STREAM_HPP
0012 
0013 #include <boost/beast/core/detail/config.hpp>
0014 #include <boost/beast/core/detail/stream_base.hpp>
0015 #include <boost/beast/core/error.hpp>
0016 #include <boost/beast/core/rate_policy.hpp>
0017 #include <boost/beast/core/role.hpp>
0018 #include <boost/beast/core/stream_traits.hpp>
0019 #include <boost/asio/async_result.hpp>
0020 #include <boost/asio/basic_stream_socket.hpp>
0021 #include <boost/asio/connect.hpp>
0022 #include <boost/asio/executor.hpp>
0023 #include <boost/asio/is_executor.hpp>
0024 #include <boost/core/empty_value.hpp>
0025 #include <boost/config/workaround.hpp>
0026 #include <boost/enable_shared_from_this.hpp>
0027 #include <boost/shared_ptr.hpp>
0028 #include <chrono>
0029 #include <limits>
0030 #include <memory>
0031 
0032 #if ! BOOST_BEAST_DOXYGEN
0033 namespace boost {
0034 namespace asio {
0035 namespace ssl {
0036 template<typename> class stream;
0037 } // ssl
0038 } // asio
0039 } // boost
0040 #endif
0041 
0042 namespace boost {
0043 namespace beast {
0044 
0045 /** A stream socket wrapper with timeouts, an executor, and a rate limit policy.
0046 
0047     This stream wraps a `net::basic_stream_socket` to provide
0048     the following features:
0049 
0050     @li An <em>Executor</em> may be associated with the stream, which will
0051     be used to invoke any completion handlers which do not already have
0052     an associated executor. This achieves support for
0053     <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1322r0.html">[P1322R0] Networking TS enhancement to enable custom I/O executors</a>.
0054 
0055     @li Timeouts may be specified for each logical asynchronous operation
0056     performing any reading, writing, or connecting.
0057 
0058     @li A <em>RatePolicy</em> may be associated with the stream, to implement
0059     rate limiting through the policy's interface.
0060 
0061     Although the stream supports multiple concurrent outstanding asynchronous
0062     operations, the stream object is not thread-safe. The caller is responsible
0063     for ensuring that the stream is accessed from only one thread at a time.
0064     This includes the times when the stream, and its underlying socket, are
0065     accessed by the networking implementation. To meet this thread safety
0066     requirement, all asynchronous operations must be performed by the stream
0067     within the same implicit strand (only one thread `net::io_context::run`)
0068     or within the same explicit strand, such as an instance of `net::strand`.
0069 
0070     Completion handlers with explicit associated executors (such as those
0071     arising from use of `net::bind_executor`) will be invoked by the stream
0072     using the associated executor. Otherwise, the completion handler will
0073     be invoked by the executor associated with the stream upon construction.
0074     The type of executor used with this stream must meet the following
0075     requirements:
0076 
0077     @li Function objects submitted to the executor shall never run
0078         concurrently with each other.
0079 
0080     The executor type `net::strand` meets these requirements. Use of a
0081     strand as the executor in the stream class template offers an additional
0082     notational convenience: the strand does not need to be specified in
0083     each individual initiating function call.
0084 
0085     Unlike other stream wrappers, the underlying socket is accessed
0086     through the @ref socket member function instead of `next_layer`.
0087     This causes the @ref basic_stream to be returned in calls
0088     to @ref get_lowest_layer.
0089 
0090     @par Usage
0091 
0092     To use this stream declare an instance of the class. Then, before
0093     each logical operation for which a timeout is desired, call
0094     @ref expires_after with a duration, or call @ref expires_at with a
0095     time point. Alternatively, call @ref expires_never to disable the
0096     timeout for subsequent logical operations. A logical operation
0097     is any series of one or more direct or indirect calls to the timeout
0098     stream's asynchronous read, asynchronous write, or asynchronous connect
0099     functions.
0100 
0101     When a timeout is set and a mixed operation is performed (one that
0102     includes both reads and writes, for example) the timeout applies
0103     to all of the intermediate asynchronous operations used in the
0104     enclosing operation. This allows timeouts to be applied to stream
0105     algorithms which were not written specifically to allow for timeouts,
0106     when those algorithms are passed a timeout stream with a timeout set.
0107 
0108     When a timeout occurs the socket will be closed, canceling any
0109     pending I/O operations. The completion handlers for these canceled
0110     operations will be invoked with the error @ref beast::error::timeout.
0111 
0112     @par Examples
0113 
0114     This function reads an HTTP request with a timeout, then sends the
0115     HTTP response with a different timeout.
0116 
0117     @code
0118     void process_http_1 (tcp_stream& stream, net::yield_context yield)
0119     {
0120         flat_buffer buffer;
0121         http::request<http::empty_body> req;
0122 
0123         // Read the request, with a 15 second timeout
0124         stream.expires_after(std::chrono::seconds(15));
0125         http::async_read(stream, buffer, req, yield);
0126 
0127         // Calculate the response
0128         http::response<http::string_body> res = make_response(req);
0129 
0130         // Send the response, with a 30 second timeout.
0131         stream.expires_after (std::chrono::seconds(30));
0132         http::async_write (stream, res, yield);
0133     }
0134     @endcode
0135 
0136     The example above could be expressed using a single timeout with a
0137     simple modification. The function that follows first reads an HTTP
0138     request then sends the HTTP response, with a single timeout that
0139     applies to the entire combined operation of reading and writing:
0140 
0141     @code
0142     void process_http_2 (tcp_stream& stream, net::yield_context yield)
0143     {
0144         flat_buffer buffer;
0145         http::request<http::empty_body> req;
0146 
0147         // Require that the read and write combined take no longer than 30 seconds
0148         stream.expires_after(std::chrono::seconds(30));
0149 
0150         http::async_read(stream, buffer, req, yield);
0151 
0152         http::response<http::string_body> res = make_response(req);
0153         http::async_write (stream, res, yield);
0154     }
0155     @endcode
0156 
0157     Some stream algorithms, such as `ssl::stream::async_handshake` perform
0158     both reads and writes. A timeout set before calling the initiating function
0159     of such composite stream algorithms will apply to the entire composite
0160     operation. For example, a timeout may be set on performing the SSL handshake
0161     thusly:
0162 
0163     @code
0164     void do_ssl_handshake (net::ssl::stream<tcp_stream>& stream, net::yield_context yield)
0165     {
0166         // Require that the SSL handshake take no longer than 10 seconds
0167         stream.expires_after(std::chrono::seconds(10));
0168 
0169         stream.async_handshake(net::ssl::stream_base::client, yield);
0170     }
0171     @endcode
0172 
0173     @par Blocking I/O
0174 
0175     Synchronous functions behave identically as that of the wrapped
0176     `net::basic_stream_socket`. Timeouts are not available when performing
0177     blocking calls.
0178 
0179     @tparam Protocol A type meeting the requirements of <em>Protocol</em>
0180     representing the protocol the protocol to use for the basic stream socket.
0181     A common choice is `net::ip::tcp`.
0182 
0183     @tparam Executor A type meeting the requirements of <em>Executor</em> to
0184     be used for submitting all completion handlers which do not already have an
0185     associated executor. If this type is omitted, the default of `net::any_io_executor`
0186     will be used.
0187 
0188     @par Thread Safety
0189     <em>Distinct objects</em>: Safe.@n
0190     <em>Shared objects</em>: Unsafe. The application must also ensure
0191     that all asynchronous operations are performed within the same
0192     implicit or explicit strand.
0193 
0194     @see
0195 
0196     @li <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1322r0.html">[P1322R0] Networking TS enhancement to enable custom I/O executors</a>.
0197 */
0198 template<
0199     class Protocol,
0200     class Executor = net::any_io_executor,
0201     class RatePolicy = unlimited_rate_policy
0202 >
0203 class basic_stream
0204 #if ! BOOST_BEAST_DOXYGEN
0205     : private detail::stream_base
0206 #endif
0207 {
0208 public:
0209     /// The type of the underlying socket.
0210     using socket_type =
0211         net::basic_stream_socket<Protocol, Executor>;
0212 
0213     /** The type of the executor associated with the stream.
0214 
0215         This will be the type of executor used to invoke completion
0216         handlers which do not have an explicit associated executor.
0217     */
0218     using executor_type = beast::executor_type<socket_type>;
0219 
0220     /// Rebinds the stream type to another executor.
0221     template<class Executor1>
0222     struct rebind_executor
0223     {
0224         /// The stream type when rebound to the specified executor.
0225         using other = basic_stream<
0226             Protocol, Executor1, RatePolicy>;
0227     };
0228 
0229     /// The protocol type.
0230     using protocol_type = Protocol;
0231 
0232     /// The endpoint type.
0233     using endpoint_type = typename Protocol::endpoint;
0234 
0235 private:
0236     using op_state = basic_op_state<Executor>;
0237     static_assert(
0238         net::is_executor<Executor>::value || net::execution::is_executor<Executor>::value,
0239         "Executor type requirements not met");
0240 
0241     struct impl_type
0242         : boost::enable_shared_from_this<impl_type>
0243         , boost::empty_value<RatePolicy>
0244     {
0245         // must come first
0246         net::basic_stream_socket<
0247             Protocol, Executor> socket;
0248 
0249         op_state read;
0250         op_state write;
0251         net::basic_waitable_timer<
0252             std::chrono::steady_clock,
0253             net::wait_traits<
0254                 std::chrono::steady_clock>,
0255             Executor> timer; // rate timer;
0256 
0257         int waiting = 0;
0258 
0259         impl_type(impl_type&&) = default;
0260 
0261         template<class... Args>
0262         explicit
0263         impl_type(std::false_type, Args&&...);
0264 
0265         template<class RatePolicy_, class... Args>
0266         explicit
0267         impl_type(std::true_type,
0268             RatePolicy_&& policy, Args&&...);
0269 
0270         impl_type& operator=(impl_type&&) = delete;
0271 
0272         beast::executor_type<socket_type>
0273         ex() noexcept
0274         {
0275             return this->socket.get_executor();
0276         }
0277 
0278         RatePolicy&
0279         policy() noexcept
0280         {
0281             return this->boost::empty_value<RatePolicy>::get();
0282         }
0283 
0284         RatePolicy const&
0285         policy() const noexcept
0286         {
0287             return this->boost::empty_value<RatePolicy>::get();
0288         }
0289 
0290         template<class Executor2>
0291         void on_timer(Executor2 const& ex2);
0292 
0293         void reset();           // set timeouts to never
0294         void close() noexcept;  // cancel everything
0295     };
0296 
0297     // We use shared ownership for the state so it can
0298     // outlive the destruction of the stream_socket object,
0299     // in the case where there is no outstanding read or write
0300     // but the implementation is still waiting on a timer.
0301     boost::shared_ptr<impl_type> impl_;
0302 
0303     template<class Executor2>
0304     struct timeout_handler;
0305 
0306     struct ops;
0307 
0308 #if ! BOOST_BEAST_DOXYGEN
0309     // boost::asio::ssl::stream needs these
0310     // DEPRECATED
0311     template<class>
0312     friend class boost::asio::ssl::stream;
0313     // DEPRECATED
0314     using lowest_layer_type = socket_type;
0315     // DEPRECATED
0316     lowest_layer_type&
0317     lowest_layer() noexcept
0318     {
0319         return impl_->socket;
0320     }
0321     // DEPRECATED
0322     lowest_layer_type const&
0323     lowest_layer() const noexcept
0324     {
0325         return impl_->socket;
0326     }
0327 #endif
0328 
0329 public:
0330     /** Destructor
0331 
0332         This function destroys the stream, cancelling any outstanding
0333         asynchronous operations associated with the socket as if by
0334         calling cancel.
0335     */
0336     ~basic_stream();
0337 
0338     /** Constructor
0339 
0340         This constructor creates the stream by forwarding all arguments
0341         to the underlying socket. The socket then needs to be open and
0342         connected or accepted before data can be sent or received on it.
0343 
0344         @param args A list of parameters forwarded to the constructor of
0345         the underlying socket.
0346     */
0347 #if BOOST_BEAST_DOXYGEN
0348     template<class... Args>
0349     explicit
0350     basic_stream(Args&&... args);
0351 #else
0352     template<class Arg0, class... Args,
0353         class = typename std::enable_if<
0354         ! std::is_constructible<RatePolicy, Arg0>::value>::type>
0355     explicit
0356     basic_stream(Arg0&& argo, Args&&... args);
0357 
0358 
0359     /** Constructor
0360      *
0361      * A constructor that rebinds the executor.
0362      *
0363      * @tparam Executor_ The new executor
0364      * @param other The original socket to be rebound.
0365      */
0366     template<class Executor_>
0367     explicit
0368     basic_stream(basic_stream<Protocol, Executor_, RatePolicy> && other);
0369 
0370 
0371     template<typename, typename, typename>
0372     friend class basic_stream;
0373 #endif
0374 
0375     /** Constructor
0376 
0377         This constructor creates the stream with the specified rate
0378         policy, and forwards all remaining arguments to the underlying
0379         socket. The socket then needs to be open and connected or
0380         accepted before data can be sent or received on it.
0381 
0382         @param policy The rate policy object to use. The stream will
0383         take ownership of this object by decay-copy.
0384 
0385         @param args A list of parameters forwarded to the constructor of
0386         the underlying socket.
0387     */
0388 #if BOOST_BEAST_DOXYGEN
0389     template<class RatePolicy_, class... Args>
0390     explicit
0391     basic_stream(RatePolicy_&& policy, Args&&... args);
0392 #else
0393     template<class RatePolicy_, class Arg0, class... Args,
0394         class = typename std::enable_if<
0395             std::is_constructible<
0396                 RatePolicy, RatePolicy_>::value>::type>
0397     basic_stream(
0398         RatePolicy_&& policy, Arg0&& arg, Args&&... args);
0399 #endif
0400 
0401     /** Move constructor
0402 
0403         @param other The other object from which the move will occur.
0404 
0405         @note Following the move, the moved-from object is in the
0406         same state as if newly constructed.
0407     */
0408     basic_stream(basic_stream&& other);
0409 
0410     /// Move assignment (deleted).
0411     basic_stream& operator=(basic_stream&&) = delete;
0412 
0413     /// Return a reference to the underlying socket
0414     socket_type&
0415     socket() noexcept
0416     {
0417         return impl_->socket;
0418     }
0419 
0420     /// Return a reference to the underlying socket
0421     socket_type const&
0422     socket() const noexcept
0423     {
0424         return impl_->socket;
0425     }
0426 
0427     /** Release ownership of the underlying socket.
0428 
0429         This function causes all outstanding asynchronous connect,
0430         read, and write operations to be canceled as if by a call
0431         to @ref cancel. Ownership of the underlying socket is then
0432         transferred to the caller.
0433     */
0434     socket_type
0435     release_socket();
0436 
0437     //--------------------------------------------------------------------------
0438 
0439     /// Returns the rate policy associated with the object
0440     RatePolicy&
0441     rate_policy() noexcept
0442     {
0443         return impl_->policy();
0444     }
0445 
0446     /// Returns the rate policy associated with the object
0447     RatePolicy const&
0448     rate_policy() const noexcept
0449     {
0450         return impl_->policy();
0451     }
0452 
0453     /** Set the timeout for the next logical operation.
0454 
0455         This sets either the read timer, the write timer, or
0456         both timers to expire after the specified amount of time
0457         has elapsed. If a timer expires when the corresponding
0458         asynchronous operation is outstanding, the stream will be
0459         closed and any outstanding operations will complete with the
0460         error @ref beast::error::timeout. Otherwise, if the timer
0461         expires while no operations are outstanding, and the expiraton
0462         is not set again, the next operation will time out immediately.
0463 
0464         The timer applies collectively to any asynchronous reads
0465         or writes initiated after the expiration is set, until the
0466         expiration is set again. A call to @ref async_connect
0467         counts as both a read and a write.
0468 
0469         @param expiry_time The amount of time after which a logical
0470         operation should be considered timed out.
0471     */
0472     void
0473     expires_after(
0474         net::steady_timer::duration expiry_time);
0475 
0476     /** Set the timeout for the next logical operation.
0477 
0478         This sets either the read timer, the write timer, or both
0479         timers to expire at the specified time point. If a timer
0480         expires when the corresponding asynchronous operation is
0481         outstanding, the stream will be closed and any outstanding
0482         operations will complete with the error @ref beast::error::timeout.
0483         Otherwise, if the timer expires while no operations are outstanding,
0484         and the expiraton is not set again, the next operation will time out
0485         immediately.
0486 
0487         The timer applies collectively to any asynchronous reads
0488         or writes initiated after the expiration is set, until the
0489         expiration is set again. A call to @ref async_connect
0490         counts as both a read and a write.
0491 
0492         @param expiry_time The time point after which a logical
0493         operation should be considered timed out.
0494     */
0495     void
0496     expires_at(net::steady_timer::time_point expiry_time);
0497 
0498     /// Disable the timeout for the next logical operation.
0499     void
0500     expires_never();
0501 
0502     /** Cancel all asynchronous operations associated with the socket.
0503 
0504         This function causes all outstanding asynchronous connect,
0505         read, and write operations to finish immediately. Completion
0506         handlers for cancelled operations will receive the error
0507         `net::error::operation_aborted`. Completion handlers not
0508         yet invoked whose operations have completed, will receive
0509         the error corresponding to the result of the operation (which
0510         may indicate success).
0511     */
0512     void
0513     cancel();
0514 
0515     /** Close the timed stream.
0516 
0517         This cancels all of the outstanding asynchronous operations
0518         as if by calling @ref cancel, and closes the underlying socket.
0519     */
0520     void
0521     close();
0522 
0523     //--------------------------------------------------------------------------
0524 
0525     /** Get the executor associated with the object.
0526 
0527         This function may be used to obtain the executor object that the
0528         stream uses to dispatch completion handlers without an assocaited
0529         executor.
0530 
0531         @return A copy of the executor that stream will use to dispatch handlers.
0532     */
0533     executor_type
0534     get_executor() noexcept
0535     {
0536         return impl_->ex();
0537     }
0538 
0539     /** Connect the stream to the specified endpoint.
0540 
0541         This function is used to connect the underlying socket to the
0542         specified remote endpoint. The function call will block until
0543         the connection is successfully made or an error occurs.
0544         The underlying socket is automatically opened if needed.
0545         An automatically opened socket is not returned to the
0546         closed state upon failure.
0547 
0548         @param ep The remote endpoint to connect to.
0549 
0550         @throws system_error Thrown on failure.
0551 
0552         @see connect
0553     */
0554     void
0555     connect(endpoint_type const& ep)
0556     {
0557         socket().connect(ep);
0558     }
0559 
0560     /** Connect the stream to the specified endpoint.
0561 
0562         This function is used to connect the underlying socket to the
0563         specified remote endpoint. The function call will block until
0564         the connection is successfully made or an error occurs.
0565         The underlying socket is automatically opened if needed.
0566         An automatically opened socket is not returned to the
0567         closed state upon failure.
0568 
0569         @param ep The remote endpoint to connect to.
0570 
0571         @param ec Set to indicate what error occurred, if any.
0572 
0573         @see connect
0574     */
0575     void
0576     connect(endpoint_type const& ep, error_code& ec)
0577     {
0578         socket().connect(ep, ec);
0579     }
0580 
0581     /** Establishes a connection by trying each endpoint in a sequence.
0582 
0583         This function attempts to connect the stream to one of a sequence of
0584         endpoints by trying each endpoint until a connection is successfully
0585         established.
0586         The underlying socket is automatically opened if needed.
0587         An automatically opened socket is not returned to the
0588         closed state upon failure.
0589 
0590         The algorithm, known as a <em>composed operation</em>, is implemented
0591         in terms of calls to the underlying socket's `connect` function.
0592 
0593         @param endpoints A sequence of endpoints.
0594 
0595         @returns The successfully connected endpoint.
0596 
0597         @throws system_error Thrown on failure. If the sequence is
0598         empty, the associated error code is `net::error::not_found`.
0599         Otherwise, contains the error from the last connection attempt.
0600     */
0601     template<class EndpointSequence
0602     #if ! BOOST_BEAST_DOXYGEN
0603         ,class = typename std::enable_if<
0604             net::is_endpoint_sequence<
0605                 EndpointSequence>::value>::type
0606     #endif
0607     >
0608     typename Protocol::endpoint
0609     connect(EndpointSequence const& endpoints)
0610     {
0611         return net::connect(socket(), endpoints);
0612     }
0613 
0614     /** Establishes a connection by trying each endpoint in a sequence.
0615 
0616         This function attempts to connect the stream to one of a sequence of
0617         endpoints by trying each endpoint until a connection is successfully
0618         established.
0619         The underlying socket is automatically opened if needed.
0620         An automatically opened socket is not returned to the
0621         closed state upon failure.
0622 
0623         The algorithm, known as a <em>composed operation</em>, is implemented
0624         in terms of calls to the underlying socket's `connect` function.
0625 
0626         @param endpoints A sequence of endpoints.
0627 
0628         @param ec Set to indicate what error occurred, if any. If the sequence is
0629         empty, set to `net::error::not_found`. Otherwise, contains the error
0630         from the last connection attempt.
0631 
0632         @returns On success, the successfully connected endpoint. Otherwise, a
0633         default-constructed endpoint.
0634     */
0635     template<class EndpointSequence
0636     #if ! BOOST_BEAST_DOXYGEN
0637         ,class = typename std::enable_if<
0638             net::is_endpoint_sequence<
0639                 EndpointSequence>::value>::type
0640     #endif
0641     >
0642     typename Protocol::endpoint
0643     connect(
0644         EndpointSequence const& endpoints,
0645         error_code& ec
0646     )
0647     {
0648         return net::connect(socket(), endpoints, ec);
0649     }
0650 
0651     /** Establishes a connection by trying each endpoint in a sequence.
0652 
0653         This function attempts to connect the stream to one of a sequence of
0654         endpoints by trying each endpoint until a connection is successfully
0655         established.
0656         The underlying socket is automatically opened if needed.
0657         An automatically opened socket is not returned to the
0658         closed state upon failure.
0659 
0660         The algorithm, known as a <em>composed operation</em>, is implemented
0661         in terms of calls to the underlying socket's `connect` function.
0662 
0663         @param begin An iterator pointing to the start of a sequence of endpoints.
0664 
0665         @param end An iterator pointing to the end of a sequence of endpoints.
0666 
0667         @returns An iterator denoting the successfully connected endpoint.
0668 
0669         @throws system_error Thrown on failure. If the sequence is
0670         empty, the associated error code is `net::error::not_found`.
0671         Otherwise, contains the error from the last connection attempt.
0672     */
0673     template<class Iterator>
0674     Iterator
0675     connect(
0676         Iterator begin, Iterator end)
0677     {
0678         return net::connect(socket(), begin, end);
0679     }
0680 
0681     /** Establishes a connection by trying each endpoint in a sequence.
0682 
0683         This function attempts to connect the stream to one of a sequence of
0684         endpoints by trying each endpoint until a connection is successfully
0685         established.
0686         The underlying socket is automatically opened if needed.
0687         An automatically opened socket is not returned to the
0688         closed state upon failure.
0689 
0690         The algorithm, known as a <em>composed operation</em>, is implemented
0691         in terms of calls to the underlying socket's `connect` function.
0692 
0693         @param begin An iterator pointing to the start of a sequence of endpoints.
0694 
0695         @param end An iterator pointing to the end of a sequence of endpoints.
0696 
0697         @param ec Set to indicate what error occurred, if any. If the sequence is
0698         empty, set to boost::asio::error::not_found. Otherwise, contains the error
0699         from the last connection attempt.
0700 
0701         @returns On success, an iterator denoting the successfully connected
0702         endpoint. Otherwise, the end iterator.
0703     */
0704     template<class Iterator>
0705     Iterator
0706     connect(
0707         Iterator begin, Iterator end,
0708         error_code& ec)
0709     {
0710         return net::connect(socket(), begin, end, ec);
0711     }
0712 
0713     /** Establishes a connection by trying each endpoint in a sequence.
0714 
0715         This function attempts to connect the stream to one of a sequence of
0716         endpoints by trying each endpoint until a connection is successfully
0717         established.
0718         The underlying socket is automatically opened if needed.
0719         An automatically opened socket is not returned to the
0720         closed state upon failure.
0721 
0722         The algorithm, known as a <em>composed operation</em>, is implemented
0723         in terms of calls to the underlying socket's `connect` function.
0724 
0725         @param endpoints A sequence of endpoints.
0726 
0727         @param connect_condition A function object that is called prior to each
0728         connection attempt. The signature of the function object must be:
0729         @code
0730         bool connect_condition(
0731             error_code const& ec,
0732             typename Protocol::endpoint const& next);
0733         @endcode
0734         The @c ec parameter contains the result from the most recent connect
0735         operation. Before the first connection attempt, @c ec is always set to
0736         indicate success. The @c next parameter is the next endpoint to be tried.
0737         The function object should return true if the next endpoint should be tried,
0738         and false if it should be skipped.
0739 
0740         @returns The successfully connected endpoint.
0741 
0742         @throws boost::system::system_error Thrown on failure. If the sequence is
0743         empty, the associated error code is `net::error::not_found`.
0744         Otherwise, contains the error from the last connection attempt.
0745     */
0746     template<
0747         class EndpointSequence, class ConnectCondition
0748     #if ! BOOST_BEAST_DOXYGEN
0749         ,class = typename std::enable_if<
0750             net::is_endpoint_sequence<
0751                 EndpointSequence>::value>::type
0752     #endif
0753     >
0754     typename Protocol::endpoint
0755     connect(
0756         EndpointSequence const& endpoints,
0757         ConnectCondition connect_condition
0758     )
0759     {
0760         return net::connect(socket(), endpoints, connect_condition);
0761     }
0762 
0763     /** Establishes a connection by trying each endpoint in a sequence.
0764 
0765         This function attempts to connect the stream to one of a sequence of
0766         endpoints by trying each endpoint until a connection is successfully
0767         established.
0768         The underlying socket is automatically opened if needed.
0769         An automatically opened socket is not returned to the
0770         closed state upon failure.
0771 
0772         The algorithm, known as a <em>composed operation</em>, is implemented
0773         in terms of calls to the underlying socket's `connect` function.
0774 
0775         @param endpoints A sequence of endpoints.
0776 
0777         @param connect_condition A function object that is called prior to each
0778         connection attempt. The signature of the function object must be:
0779         @code
0780         bool connect_condition(
0781             error_code const& ec,
0782             typename Protocol::endpoint const& next);
0783         @endcode
0784         The @c ec parameter contains the result from the most recent connect
0785         operation. Before the first connection attempt, @c ec is always set to
0786         indicate success. The @c next parameter is the next endpoint to be tried.
0787         The function object should return true if the next endpoint should be tried,
0788         and false if it should be skipped.
0789 
0790         @param ec Set to indicate what error occurred, if any. If the sequence is
0791         empty, set to `net::error::not_found`. Otherwise, contains the error
0792         from the last connection attempt.
0793 
0794         @returns On success, the successfully connected endpoint. Otherwise, a
0795         default-constructed endpoint.
0796     */
0797     template<
0798         class EndpointSequence, class ConnectCondition
0799     #if ! BOOST_BEAST_DOXYGEN
0800         ,class = typename std::enable_if<
0801             net::is_endpoint_sequence<
0802                 EndpointSequence>::value>::type
0803     #endif
0804     >
0805     typename Protocol::endpoint
0806     connect(
0807         EndpointSequence const& endpoints,
0808         ConnectCondition connect_condition,
0809         error_code& ec)
0810     {
0811         return net::connect(socket(), endpoints, connect_condition, ec);
0812     }
0813 
0814     /** Establishes a connection by trying each endpoint in a sequence.
0815 
0816         This function attempts to connect the stream to one of a sequence of
0817         endpoints by trying each endpoint until a connection is successfully
0818         established.
0819         The underlying socket is automatically opened if needed.
0820         An automatically opened socket is not returned to the
0821         closed state upon failure.
0822 
0823         The algorithm, known as a <em>composed operation</em>, is implemented
0824         in terms of calls to the underlying socket's `connect` function.
0825 
0826         @param begin An iterator pointing to the start of a sequence of endpoints.
0827 
0828         @param end An iterator pointing to the end of a sequence of endpoints.
0829 
0830         @param connect_condition A function object that is called prior to each
0831         connection attempt. The signature of the function object must be:
0832         @code
0833         bool connect_condition(
0834             error_code const& ec,
0835             typename Protocol::endpoint const& next);
0836         @endcode
0837         The @c ec parameter contains the result from the most recent connect
0838         operation. Before the first connection attempt, @c ec is always set to
0839         indicate success. The @c next parameter is the next endpoint to be tried.
0840         The function object should return true if the next endpoint should be tried,
0841         and false if it should be skipped.
0842 
0843         @returns An iterator denoting the successfully connected endpoint.
0844 
0845         @throws boost::system::system_error Thrown on failure. If the sequence is
0846         empty, the associated @c error_code is `net::error::not_found`.
0847         Otherwise, contains the error from the last connection attempt.
0848     */
0849     template<
0850         class Iterator, class ConnectCondition>
0851     Iterator
0852     connect(
0853         Iterator begin, Iterator end,
0854         ConnectCondition connect_condition)
0855     {
0856         return net::connect(socket(), begin, end, connect_condition);
0857     }
0858 
0859     /** Establishes a connection by trying each endpoint in a sequence.
0860 
0861         This function attempts to connect the stream to one of a sequence of
0862         endpoints by trying each endpoint until a connection is successfully
0863         established.
0864         The underlying socket is automatically opened if needed.
0865         An automatically opened socket is not returned to the
0866         closed state upon failure.
0867 
0868         The algorithm, known as a <em>composed operation</em>, is implemented
0869         in terms of calls to the underlying socket's `connect` function.
0870 
0871         @param begin An iterator pointing to the start of a sequence of endpoints.
0872 
0873         @param end An iterator pointing to the end of a sequence of endpoints.
0874 
0875         @param connect_condition A function object that is called prior to each
0876         connection attempt. The signature of the function object must be:
0877         @code
0878         bool connect_condition(
0879             error_code const& ec,
0880             typename Protocol::endpoint const& next);
0881         @endcode
0882         The @c ec parameter contains the result from the most recent connect
0883         operation. Before the first connection attempt, @c ec is always set to
0884         indicate success. The @c next parameter is the next endpoint to be tried.
0885         The function object should return true if the next endpoint should be tried,
0886         and false if it should be skipped.
0887 
0888         @param ec Set to indicate what error occurred, if any. If the sequence is
0889         empty, set to `net::error::not_found`. Otherwise, contains the error
0890         from the last connection attempt.
0891 
0892         @returns On success, an iterator denoting the successfully connected
0893         endpoint. Otherwise, the end iterator.
0894     */
0895     template<
0896         class Iterator, class ConnectCondition>
0897     Iterator
0898     connect(
0899         Iterator begin, Iterator end,
0900         ConnectCondition connect_condition,
0901         error_code& ec)
0902     {
0903         return net::connect(socket(), begin, end, connect_condition, ec);
0904     }
0905 
0906     /** Connect the stream to the specified endpoint asynchronously.
0907 
0908         This function is used to asynchronously connect the underlying
0909         socket to the specified remote endpoint. The function call always
0910         returns immediately.
0911         The underlying socket is automatically opened if needed.
0912         An automatically opened socket is not returned to the
0913         closed state upon failure.
0914 
0915         If the timeout timer expires while the operation is outstanding,
0916         the operation will be canceled and the completion handler will be
0917         invoked with the error @ref error::timeout.
0918 
0919         @param ep The remote endpoint to which the underlying socket will be
0920         connected. Copies will be made of the endpoint object as required.
0921 
0922         @param handler The completion handler to invoke when the operation
0923         completes. The implementation takes ownership of the handler by
0924         performing a decay-copy. The equivalent function signature of
0925         the handler must be:
0926         @code
0927         void handler(
0928             error_code ec         // Result of operation
0929         );
0930         @endcode
0931         If the handler has an associated immediate executor,
0932         an immediate completion will be dispatched to it.
0933         Otherwise, the handler will not be invoked from within
0934         this function. Invocation of the handler will be performed
0935         by dispatching to the immediate executor. If no
0936         immediate executor is specified, this is equivalent
0937         to using `net::post`.
0938 
0939         @par Per-Operation Cancellation
0940 
0941         This asynchronous operation supports cancellation for the following
0942         net::cancellation_type values:
0943 
0944         @li @c net::cancellation_type::terminal
0945         @li @c net::cancellation_type::partial
0946         @li @c net::cancellation_type::total
0947 
0948         if they are also supported by the socket's @c async_connect operation.
0949 
0950         @see async_connect
0951     */
0952     template<
0953         BOOST_BEAST_ASYNC_TPARAM1 ConnectHandler =
0954             net::default_completion_token_t<executor_type>
0955     >
0956     BOOST_BEAST_ASYNC_RESULT1(ConnectHandler)
0957     async_connect(
0958         endpoint_type const& ep,
0959         ConnectHandler&& handler =
0960             net::default_completion_token_t<
0961                 executor_type>{});
0962 
0963     /** Establishes a connection by trying each endpoint in a sequence asynchronously.
0964 
0965         This function attempts to connect the stream to one of a sequence of
0966         endpoints by trying each endpoint until a connection is successfully
0967         established.
0968         The underlying socket is automatically opened if needed.
0969         An automatically opened socket is not returned to the
0970         closed state upon failure.
0971 
0972         The algorithm, known as a <em>composed asynchronous operation</em>, is
0973         implemented in terms of calls to the underlying socket's `async_connect`
0974         function.
0975 
0976         If the timeout timer expires while the operation is outstanding,
0977         the current connection attempt will be canceled and the completion
0978         handler will be invoked with the error @ref error::timeout.
0979 
0980         @param endpoints A sequence of endpoints. This this object must meet
0981         the requirements of <em>EndpointSequence</em>.
0982 
0983         @param handler The completion handler to invoke when the operation
0984         completes. The implementation takes ownership of the handler by
0985         performing a decay-copy. The equivalent function signature of
0986         the handler must be:
0987         @code
0988         void handler(
0989             // Result of operation. if the sequence is empty, set to
0990             // net::error::not_found. Otherwise, contains the
0991             // error from the last connection attempt.
0992             error_code const& error,
0993 
0994             // On success, the successfully connected endpoint.
0995             // Otherwise, a default-constructed endpoint.
0996             typename Protocol::endpoint const& endpoint
0997         );
0998         @endcode
0999         If the handler has an associated immediate executor,
1000         an immediate completion will be dispatched to it.
1001         Otherwise, the handler will not be invoked from within
1002         this function. Invocation of the handler will be performed
1003         by dispatching to the immediate executor. If no
1004         immediate executor is specified, this is equivalent
1005         to using `net::post`.
1006 
1007         @par Per-Operation Cancellation
1008 
1009         This asynchronous operation supports cancellation for the following
1010         net::cancellation_type values:
1011 
1012         @li @c net::cancellation_type::terminal
1013         @li @c net::cancellation_type::partial
1014         @li @c net::cancellation_type::total
1015 
1016         if they are also supported by the socket's @c async_connect operation.
1017 
1018     */
1019     template<
1020         class EndpointSequence,
1021         BOOST_ASIO_COMPLETION_TOKEN_FOR(
1022             void(error_code, typename Protocol::endpoint))
1023             RangeConnectHandler =
1024                 net::default_completion_token_t<executor_type>
1025     #if ! BOOST_BEAST_DOXYGEN
1026         ,class = typename std::enable_if<
1027             net::is_endpoint_sequence<
1028                 EndpointSequence>::value>::type
1029     #endif
1030     >
1031     BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
1032         RangeConnectHandler,
1033         void(error_code, typename Protocol::endpoint))
1034     async_connect(
1035         EndpointSequence const& endpoints,
1036         RangeConnectHandler&& handler =
1037             net::default_completion_token_t<executor_type>{});
1038 
1039     /** Establishes a connection by trying each endpoint in a sequence asynchronously.
1040 
1041         This function attempts to connect the stream to one of a sequence of
1042         endpoints by trying each endpoint until a connection is successfully
1043         established.
1044         The underlying socket is automatically opened if needed.
1045         An automatically opened socket is not returned to the
1046         closed state upon failure.
1047 
1048         The algorithm, known as a <em>composed asynchronous operation</em>, is
1049         implemented in terms of calls to the underlying socket's `async_connect`
1050         function.
1051 
1052         If the timeout timer expires while the operation is outstanding,
1053         the current connection attempt will be canceled and the completion
1054         handler will be invoked with the error @ref error::timeout.
1055 
1056         @param endpoints A sequence of endpoints. This this object must meet
1057         the requirements of <em>EndpointSequence</em>.
1058 
1059         @param connect_condition A function object that is called prior to each
1060         connection attempt. The signature of the function object must be:
1061         @code
1062         bool connect_condition(
1063             error_code const& ec,
1064             typename Protocol::endpoint const& next);
1065         @endcode
1066         The @c ec parameter contains the result from the most recent connect
1067         operation. Before the first connection attempt, @c ec is always set to
1068         indicate success. The @c next parameter is the next endpoint to be tried.
1069         The function object should return true if the next endpoint should be tried,
1070         and false if it should be skipped.
1071 
1072         @param handler The completion handler to invoke when the operation
1073         completes. The implementation takes ownership of the handler by
1074         performing a decay-copy. The equivalent function signature of
1075         the handler must be:
1076         @code
1077         void handler(
1078             // Result of operation. if the sequence is empty, set to
1079             // net::error::not_found. Otherwise, contains the
1080             // error from the last connection attempt.
1081             error_code const& error,
1082 
1083             // On success, the successfully connected endpoint.
1084             // Otherwise, a default-constructed endpoint.
1085             typename Protocol::endpoint const& endpoint
1086         );
1087         @endcode
1088         If the handler has an associated immediate executor,
1089         an immediate completion will be dispatched to it.
1090         Otherwise, the handler will not be invoked from within
1091         this function. Invocation of the handler will be performed
1092         by dispatching to the immediate executor. If no
1093         immediate executor is specified, this is equivalent
1094         to using `net::post`.
1095         @par Example
1096         The following connect condition function object can be used to output
1097         information about the individual connection attempts:
1098         @code
1099         struct my_connect_condition
1100         {
1101             bool operator()(
1102                 error_code const& ec,
1103                 net::ip::tcp::endpoint const& next)
1104             {
1105                 if (ec)
1106                     std::cout << "Error: " << ec.message() << std::endl;
1107                 std::cout << "Trying: " << next << std::endl;
1108                 return true;
1109             }
1110         };
1111         @endcode
1112 
1113         @par Per-Operation Cancellation
1114 
1115         This asynchronous operation supports cancellation for the following
1116         net::cancellation_type values:
1117 
1118         @li @c net::cancellation_type::terminal
1119         @li @c net::cancellation_type::partial
1120         @li @c net::cancellation_type::total
1121 
1122         if they are also supported by the socket's @c async_connect operation.
1123     */
1124     template<
1125         class EndpointSequence,
1126         class ConnectCondition,
1127         BOOST_ASIO_COMPLETION_TOKEN_FOR(
1128             void(error_code, typename Protocol::endpoint))
1129             RangeConnectHandler =
1130                 net::default_completion_token_t<executor_type>
1131     #if ! BOOST_BEAST_DOXYGEN
1132         ,class = typename std::enable_if<
1133             net::is_endpoint_sequence<
1134                 EndpointSequence>::value>::type
1135     #endif
1136     >
1137     BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
1138         RangeConnectHandler,
1139         void(error_code, typename Protocol::endpoint))
1140     async_connect(
1141         EndpointSequence const& endpoints,
1142         ConnectCondition connect_condition,
1143         RangeConnectHandler&& handler =
1144             net::default_completion_token_t<
1145                 executor_type>{});
1146 
1147     /** Establishes a connection by trying each endpoint in a sequence asynchronously.
1148 
1149         This function attempts to connect the stream to one of a sequence of
1150         endpoints by trying each endpoint until a connection is successfully
1151         established.
1152         The underlying socket is automatically opened if needed.
1153         An automatically opened socket is not returned to the
1154         closed state upon failure.
1155 
1156         The algorithm, known as a <em>composed asynchronous operation</em>, is
1157         implemented in terms of calls to the underlying socket's `async_connect`
1158         function.
1159 
1160         If the timeout timer expires while the operation is outstanding,
1161         the current connection attempt will be canceled and the completion
1162         handler will be invoked with the error @ref error::timeout.
1163 
1164         @param begin An iterator pointing to the start of a sequence of endpoints.
1165 
1166         @param end An iterator pointing to the end of a sequence of endpoints.
1167 
1168         @param handler The completion handler to invoke when the operation
1169         completes. The implementation takes ownership of the handler by
1170         performing a decay-copy. The equivalent function signature of
1171         the handler must be:
1172         @code
1173         void handler(
1174             // Result of operation. if the sequence is empty, set to
1175             // net::error::not_found. Otherwise, contains the
1176             // error from the last connection attempt.
1177             error_code const& error,
1178 
1179             // On success, an iterator denoting the successfully
1180             // connected endpoint. Otherwise, the end iterator.
1181             Iterator iterator
1182         );
1183         @endcode
1184         If the handler has an associated immediate executor,
1185         an immediate completion will be dispatched to it.
1186         Otherwise, the handler will not be invoked from within
1187         this function. Invocation of the handler will be performed
1188         by dispatching to the immediate executor. If no
1189         immediate executor is specified, this is equivalent
1190         to using `net::post`.
1191         @par Per-Operation Cancellation
1192 
1193         This asynchronous operation supports cancellation for the following
1194         net::cancellation_type values:
1195 
1196         @li @c net::cancellation_type::terminal
1197         @li @c net::cancellation_type::partial
1198         @li @c net::cancellation_type::total
1199 
1200         if they are also supported by the socket's @c async_connect operation.
1201     */
1202     template<
1203         class Iterator,
1204         BOOST_ASIO_COMPLETION_TOKEN_FOR(
1205             void(error_code, Iterator))
1206             IteratorConnectHandler =
1207                 net::default_completion_token_t<executor_type>>
1208     BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
1209         IteratorConnectHandler,
1210         void(error_code, Iterator))
1211     async_connect(
1212         Iterator begin, Iterator end,
1213         IteratorConnectHandler&& handler =
1214             net::default_completion_token_t<executor_type>{});
1215 
1216     /** Establishes a connection by trying each endpoint in a sequence asynchronously.
1217 
1218         This function attempts to connect the stream to one of a sequence of
1219         endpoints by trying each endpoint until a connection is successfully
1220         established.
1221         The algorithm, known as a <em>composed asynchronous operation</em>, is
1222         implemented in terms of calls to the underlying socket's `async_connect`
1223         function.
1224 
1225         If the timeout timer expires while the operation is outstanding,
1226         the current connection attempt will be canceled and the completion
1227         handler will be invoked with the error @ref error::timeout.
1228 
1229         @param begin An iterator pointing to the start of a sequence of endpoints.
1230 
1231         @param end An iterator pointing to the end of a sequence of endpoints.
1232 
1233         @param connect_condition A function object that is called prior to each
1234         connection attempt. The signature of the function object must be:
1235         @code
1236         bool connect_condition(
1237             error_code const& ec,
1238             typename Protocol::endpoint const& next);
1239         @endcode
1240 
1241         @param handler The completion handler to invoke when the operation
1242         completes. The implementation takes ownership of the handler by
1243         performing a decay-copy. The equivalent function signature of
1244         the handler must be:
1245         @code
1246         void handler(
1247             // Result of operation. if the sequence is empty, set to
1248             // net::error::not_found. Otherwise, contains the
1249             // error from the last connection attempt.
1250             error_code const& error,
1251 
1252             // On success, an iterator denoting the successfully
1253             // connected endpoint. Otherwise, the end iterator.
1254             Iterator iterator
1255         );
1256         @endcode
1257         If the handler has an associated immediate executor,
1258         an immediate completion will be dispatched to it.
1259         Otherwise, the handler will not be invoked from within
1260         this function. Invocation of the handler will be performed
1261         by dispatching to the immediate executor. If no
1262         immediate executor is specified, this is equivalent
1263         to using `net::post`.
1264         @par Per-Operation Cancellation
1265 
1266         This asynchronous operation supports cancellation for the following
1267         net::cancellation_type values:
1268 
1269         @li @c net::cancellation_type::terminal
1270         @li @c net::cancellation_type::partial
1271         @li @c net::cancellation_type::total
1272 
1273         if they are also supported by the socket's @c async_connect operation.
1274     */
1275     template<
1276         class Iterator,
1277         class ConnectCondition,
1278         BOOST_ASIO_COMPLETION_TOKEN_FOR(
1279             void(error_code, Iterator))
1280             IteratorConnectHandler =
1281                 net::default_completion_token_t<executor_type>>
1282     BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
1283         IteratorConnectHandler,
1284         void(error_code, Iterator))
1285     async_connect(
1286         Iterator begin, Iterator end,
1287         ConnectCondition connect_condition,
1288         IteratorConnectHandler&& handler =
1289             net::default_completion_token_t<executor_type>{});
1290 
1291     //--------------------------------------------------------------------------
1292 
1293     /** Read some data.
1294 
1295         This function is used to read some data from the stream.
1296 
1297         The call blocks until one of the following is true:
1298 
1299         @li One or more bytes are read from the stream.
1300 
1301         @li An error occurs.
1302 
1303         @param buffers The buffers into which the data will be read. If the
1304         size of the buffers is zero bytes, the call always returns
1305         immediately with no error.
1306 
1307         @returns The number of bytes read.
1308 
1309         @throws system_error Thrown on failure.
1310 
1311         @note The `read_some` operation may not receive all of the requested
1312         number of bytes. Consider using the function `net::read` if you need
1313         to ensure that the requested amount of data is read before the
1314         blocking operation completes.
1315     */
1316     template<class MutableBufferSequence>
1317     std::size_t
1318     read_some(MutableBufferSequence const& buffers)
1319     {
1320         return impl_->socket.read_some(buffers);
1321     }
1322 
1323     /** Read some data.
1324 
1325         This function is used to read some data from the underlying socket.
1326 
1327         The call blocks until one of the following is true:
1328 
1329         @li One or more bytes are read from the stream.
1330 
1331         @li An error occurs.
1332 
1333         @param buffers The buffers into which the data will be read. If the
1334         size of the buffers is zero bytes, the call always returns
1335         immediately with no error.
1336 
1337         @param ec Set to indicate what error occurred, if any.
1338 
1339         @returns The number of bytes read.
1340 
1341         @note The `read_some` operation may not receive all of the requested
1342         number of bytes. Consider using the function `net::read` if you need
1343         to ensure that the requested amount of data is read before the
1344         blocking operation completes.
1345     */
1346     template<class MutableBufferSequence>
1347     std::size_t
1348     read_some(
1349         MutableBufferSequence const& buffers,
1350         error_code& ec)
1351     {
1352         return impl_->socket.read_some(buffers, ec);
1353     }
1354 
1355     /** Read some data asynchronously.
1356 
1357         This function is used to asynchronously read data from the stream.
1358 
1359         This call always returns immediately. The asynchronous operation
1360         will continue until one of the following conditions is true:
1361 
1362         @li One or more bytes are read from the stream.
1363 
1364         @li An error occurs.
1365 
1366         The algorithm, known as a <em>composed asynchronous operation</em>,
1367         is implemented in terms of calls to the next layer's `async_read_some`
1368         function. The program must ensure that no other calls to @ref read_some
1369         or @ref async_read_some are performed until this operation completes.
1370 
1371         If the timeout timer expires while the operation is outstanding,
1372         the operation will be canceled and the completion handler will be
1373         invoked with the error @ref error::timeout.
1374 
1375         @param buffers The buffers into which the data will be read. If the size
1376         of the buffers is zero bytes, the operation always completes immediately
1377         with no error.
1378         Although the buffers object may be copied as necessary, ownership of the
1379         underlying memory blocks is retained by the caller, which must guarantee
1380         that they remain valid until the handler is called.
1381 
1382         @param handler The completion handler to invoke when the operation
1383         completes. The implementation takes ownership of the handler by
1384         performing a decay-copy. The equivalent function signature of
1385         the handler must be:
1386         @code
1387         void handler(
1388             error_code error,               // Result of operation.
1389             std::size_t bytes_transferred   // Number of bytes read.
1390         );
1391         @endcode
1392         If the handler has an associated immediate executor,
1393         an immediate completion will be dispatched to it.
1394         Otherwise, the handler will not be invoked from within
1395         this function. Invocation of the handler will be performed
1396         by dispatching to the immediate executor. If no
1397         immediate executor is specified, this is equivalent
1398         to using `net::post`.
1399         @note The `async_read_some` operation may not receive all of the requested
1400         number of bytes. Consider using the function `net::async_read` if you need
1401         to ensure that the requested amount of data is read before the asynchronous
1402         operation completes.
1403 
1404         @par Per-Operation Cancellation
1405 
1406         This asynchronous operation supports cancellation for the following
1407         net::cancellation_type values:
1408 
1409         @li @c net::cancellation_type::terminal
1410         @li @c net::cancellation_type::partial
1411         @li @c net::cancellation_type::total
1412 
1413         if they are also supported by the socket's @c async_read_some operation.
1414     */
1415     template<
1416         class MutableBufferSequence,
1417         BOOST_BEAST_ASYNC_TPARAM2 ReadHandler =
1418             net::default_completion_token_t<executor_type>
1419     >
1420     BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
1421     async_read_some(
1422         MutableBufferSequence const& buffers,
1423         ReadHandler&& handler =
1424             net::default_completion_token_t<executor_type>{}
1425     );
1426 
1427     /** Write some data.
1428 
1429         This function is used to write some data to the stream.
1430 
1431         The call blocks until one of the following is true:
1432 
1433         @li One or more bytes are written to the stream.
1434 
1435         @li An error occurs.
1436 
1437         @param buffers The buffers from which the data will be written. If the
1438         size of the buffers is zero bytes, the call always returns immediately
1439         with no error.
1440 
1441         @returns The number of bytes written.
1442 
1443         @throws system_error Thrown on failure.
1444 
1445         @note The `write_some` operation may not transmit all of the requested
1446         number of bytes. Consider using the function `net::write` if you need
1447         to ensure that the requested amount of data is written before the
1448         blocking operation completes.
1449     */
1450     template<class ConstBufferSequence>
1451     std::size_t
1452     write_some(ConstBufferSequence const& buffers)
1453     {
1454         return impl_->socket.write_some(buffers);
1455     }
1456 
1457     /** Write some data.
1458 
1459         This function is used to write some data to the stream.
1460 
1461         The call blocks until one of the following is true:
1462 
1463         @li One or more bytes are written to the stream.
1464 
1465         @li An error occurs.
1466 
1467         @param buffers The buffers from which the data will be written. If the
1468         size of the buffers is zero bytes, the call always returns immediately
1469         with no error.
1470 
1471         @param ec Set to indicate what error occurred, if any.
1472 
1473         @returns The number of bytes written.
1474 
1475         @throws system_error Thrown on failure.
1476 
1477         @note The `write_some` operation may not transmit all of the requested
1478         number of bytes. Consider using the function `net::write` if you need
1479         to ensure that the requested amount of data is written before the
1480         blocking operation completes.
1481     */
1482     template<class ConstBufferSequence>
1483     std::size_t
1484     write_some(
1485         ConstBufferSequence const& buffers,
1486         error_code& ec)
1487     {
1488         return impl_->socket.write_some(buffers, ec);
1489     }
1490 
1491     /** Write some data asynchronously.
1492 
1493         This function is used to asynchronously write data to the underlying socket.
1494 
1495         This call always returns immediately. The asynchronous operation
1496         will continue until one of the following conditions is true:
1497 
1498         @li One or more bytes are written to the stream.
1499 
1500         @li An error occurs.
1501 
1502         The algorithm, known as a <em>composed asynchronous operation</em>,
1503         is implemented in terms of calls to the next layer's `async_write_some`
1504         function. The program must ensure that no other calls to @ref async_write_some
1505         are performed until this operation completes.
1506 
1507         If the timeout timer expires while the operation is outstanding,
1508         the operation will be canceled and the completion handler will be
1509         invoked with the error @ref error::timeout.
1510 
1511         @param buffers The buffers from which the data will be written. If the
1512         size of the buffers is zero bytes, the operation  always completes
1513         immediately with no error.
1514         Although the buffers object may be copied as necessary, ownership of the
1515         underlying memory blocks is retained by the caller, which must guarantee
1516         that they remain valid until the handler is called.
1517 
1518         @param handler The completion handler to invoke when the operation
1519         completes. The implementation takes ownership of the handler by
1520         performing a decay-copy. The equivalent function signature of
1521         the handler must be:
1522         @code
1523         void handler(
1524             error_code error,               // Result of operation.
1525             std::size_t bytes_transferred   // Number of bytes written.
1526         );
1527         @endcode
1528         If the handler has an associated immediate executor,
1529         an immediate completion will be dispatched to it.
1530         Otherwise, the handler will not be invoked from within
1531         this function. Invocation of the handler will be performed
1532         by dispatching to the immediate executor. If no
1533         immediate executor is specified, this is equivalent
1534         to using `net::post`.
1535         @note The `async_write_some` operation may not transmit all of the requested
1536         number of bytes. Consider using the function `net::async_write` if you need
1537         to ensure that the requested amount of data is sent before the asynchronous
1538         operation completes.
1539 
1540         @par Per-Operation Cancellation
1541 
1542         This asynchronous operation supports cancellation for the following
1543         net::cancellation_type values:
1544 
1545         @li @c net::cancellation_type::terminal
1546         @li @c net::cancellation_type::partial
1547         @li @c net::cancellation_type::total
1548 
1549         if they are also supported by the socket's @c async_write_some operation.
1550     */
1551     template<
1552         class ConstBufferSequence,
1553         BOOST_BEAST_ASYNC_TPARAM2 WriteHandler =
1554             net::default_completion_token_t<Executor>
1555     >
1556     BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
1557     async_write_some(
1558         ConstBufferSequence const& buffers,
1559         WriteHandler&& handler =
1560             net::default_completion_token_t<Executor>{});
1561 };
1562 
1563 } // beast
1564 } // boost
1565 
1566 #include <boost/beast/core/impl/basic_stream.hpp>
1567 
1568 #endif