Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / beast / core / basic_stream.hpp
1 //
2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/beast
8 //
9
10 #ifndef BOOST_BEAST_CORE_BASIC_STREAM_HPP
11 #define BOOST_BEAST_CORE_BASIC_STREAM_HPP
12
13 #include <boost/beast/core/detail/config.hpp>
14 #include <boost/beast/core/detail/stream_base.hpp>
15 #include <boost/beast/core/error.hpp>
16 #include <boost/beast/core/rate_policy.hpp>
17 #include <boost/beast/core/role.hpp>
18 #include <boost/beast/core/stream_traits.hpp>
19 #include <boost/asio/async_result.hpp>
20 #include <boost/asio/basic_stream_socket.hpp>
21 #include <boost/asio/connect.hpp>
22 #include <boost/asio/executor.hpp>
23 #include <boost/asio/is_executor.hpp>
24 #include <boost/core/empty_value.hpp>
25 #include <boost/config/workaround.hpp>
26 #include <boost/enable_shared_from_this.hpp>
27 #include <boost/shared_ptr.hpp>
28 #include <chrono>
29 #include <limits>
30 #include <memory>
31
32 #if ! BOOST_BEAST_DOXYGEN
33 namespace boost {
34 namespace asio {
35 namespace ssl {
36 template<typename> class stream;
37 } // ssl
38 } // asio
39 } // boost
40 #endif
41
42 namespace boost {
43 namespace beast {
44
45 /** A stream socket wrapper with timeouts, an executor, and a rate limit policy.
46
47     This stream wraps a `net::basic_stream_socket` to provide
48     the following features:
49
50     @li An <em>Executor</em> may be associated with the stream, which will
51     be used to invoke any completion handlers which do not already have
52     an associated executor. This achieves support for
53     <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>.
54
55     @li Timeouts may be specified for each logical asynchronous operation
56     performing any reading, writing, or connecting.
57
58     @li A <em>RatePolicy</em> may be associated with the stream, to implement
59     rate limiting through the policy's interface.
60
61     Although the stream supports multiple concurrent outstanding asynchronous
62     operations, the stream object is not thread-safe. The caller is responsible
63     for ensuring that the stream is accessed from only one thread at a time.
64     This includes the times when the stream, and its underlying socket, are
65     accessed by the networking implementation. To meet this thread safety
66     requirement, all asynchronous operations must be performed by the stream
67     within the same implicit strand (only one thread `net::io_context::run`)
68     or within the same explicit strand, such as an instance of `net::strand`.
69
70     Completion handlers with explicit associated executors (such as those
71     arising from use of `net::bind_executor`) will be invoked by the stream
72     using the associated executor. Otherwise, the completion handler will
73     be invoked by the executor associated with the stream upon construction.
74     The type of executor used with this stream must meet the following
75     requirements:
76
77     @li Function objects submitted to the executor shall never run
78         concurrently with each other.
79
80     The executor type `net::strand` meets these requirements. Use of a
81     strand as the executor in the stream class template offers an additional
82     notational convenience: the strand does not need to be specified in
83     each individual initiating function call.
84
85     Unlike other stream wrappers, the underlying socket is accessed
86     through the @ref socket member function instead of `next_layer`.
87     This causes the @ref basic_stream to be returned in calls
88     to @ref get_lowest_layer.
89
90     @par Usage
91
92     To use this stream declare an instance of the class. Then, before
93     each logical operation for which a timeout is desired, call
94     @ref expires_after with a duration, or call @ref expires_at with a
95     time point. Alternatively, call @ref expires_never to disable the
96     timeout for subsequent logical operations. A logical operation
97     is any series of one or more direct or indirect calls to the timeout
98     stream's asynchronous read, asynchronous write, or asynchronous connect
99     functions.
100
101     When a timeout is set and a mixed operation is performed (one that
102     includes both reads and writes, for example) the timeout applies
103     to all of the intermediate asynchronous operations used in the
104     enclosing operation. This allows timeouts to be applied to stream
105     algorithms which were not written specifically to allow for timeouts,
106     when those algorithms are passed a timeout stream with a timeout set.
107
108     When a timeout occurs the socket will be closed, canceling any
109     pending I/O operations. The completion handlers for these canceled
110     operations will be invoked with the error @ref beast::error::timeout.
111
112     @par Examples
113
114     This function reads an HTTP request with a timeout, then sends the
115     HTTP response with a different timeout.
116
117     @code
118     void process_http_1 (tcp_stream& stream, net::yield_context yield)
119     {
120         flat_buffer buffer;
121         http::request<http::empty_body> req;
122
123         // Read the request, with a 15 second timeout
124         stream.expires_after(std::chrono::seconds(15));
125         http::async_read(stream, buffer, req, yield);
126
127         // Calculate the response
128         http::response<http::string_body> res = make_response(req);
129
130         // Send the response, with a 30 second timeout.
131         stream.expires_after (std::chrono::seconds(30));
132         http::async_write (stream, res, yield);
133     }
134     @endcode
135
136     The example above could be expressed using a single timeout with a
137     simple modification. The function that follows first reads an HTTP
138     request then sends the HTTP response, with a single timeout that
139     applies to the entire combined operation of reading and writing:
140
141     @code
142     void process_http_2 (tcp_stream& stream, net::yield_context yield)
143     {
144         flat_buffer buffer;
145         http::request<http::empty_body> req;
146
147         // Require that the read and write combined take no longer than 30 seconds
148         stream.expires_after(std::chrono::seconds(30));
149
150         http::async_read(stream, buffer, req, yield);
151
152         http::response<http::string_body> res = make_response(req);
153         http::async_write (stream, res, yield);
154     }
155     @endcode
156
157     Some stream algorithms, such as `ssl::stream::async_handshake` perform
158     both reads and writes. A timeout set before calling the initiating function
159     of such composite stream algorithms will apply to the entire composite
160     operation. For example, a timeout may be set on performing the SSL handshake
161     thusly:
162
163     @code
164     void do_ssl_handshake (net::ssl::stream<tcp_stream>& stream, net::yield_context yield)
165     {
166         // Require that the SSL handshake take no longer than 10 seconds
167         stream.expires_after(std::chrono::seconds(10));
168
169         stream.async_handshake(net::ssl::stream_base::client, yield);
170     }
171     @endcode
172
173     @par Blocking I/O
174
175     Synchronous functions behave identically as that of the wrapped
176     `net::basic_stream_socket`. Timeouts are not available when performing
177     blocking calls.
178
179     @tparam Protocol A type meeting the requirements of <em>Protocol</em>
180     representing the protocol the protocol to use for the basic stream socket.
181     A common choice is `net::ip::tcp`.
182
183     @tparam Executor A type meeting the requirements of <em>Executor</em> to
184     be used for submitting all completion handlers which do not already have an
185     associated executor. If this type is omitted, the default of `net::executor`
186     will be used.
187
188     @par Thread Safety
189     <em>Distinct objects</em>: Safe.@n
190     <em>Shared objects</em>: Unsafe. The application must also ensure
191     that all asynchronous operations are performed within the same
192     implicit or explicit strand.
193
194     @see
195
196     @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>.
197 */
198 template<
199     class Protocol,
200     class Executor = net::executor,
201     class RatePolicy = unlimited_rate_policy
202 >
203 class basic_stream
204 #if ! BOOST_BEAST_DOXYGEN
205     : private detail::stream_base
206 #endif
207 {
208 public:
209     /// The type of the underlying socket.
210     using socket_type =
211         net::basic_stream_socket<Protocol, Executor>;
212
213     /** The type of the executor associated with the stream.
214
215         This will be the type of executor used to invoke completion
216         handlers which do not have an explicit associated executor.
217     */
218     using executor_type = beast::executor_type<socket_type>;
219
220     /// Rebinds the stream type to another executor.
221     template<class Executor1>
222     struct rebind_executor
223     {
224         /// The stream type when rebound to the specified executor.
225         using other = basic_stream<
226             Protocol, Executor1, RatePolicy>;
227     };
228
229     /// The protocol type.
230     using protocol_type = Protocol;
231
232     /// The endpoint type.
233     using endpoint_type = typename Protocol::endpoint;
234
235 private:
236     static_assert(net::is_executor<Executor>::value,
237         "Executor type requirements not met");
238
239     struct impl_type
240         : boost::enable_shared_from_this<impl_type>
241         , boost::empty_value<RatePolicy>
242     {
243         // must come first
244         net::basic_stream_socket<
245             Protocol, Executor> socket;
246
247         op_state read;
248         op_state write;
249 #if 0
250         net::basic_waitable_timer<
251             std::chrono::steady_clock,
252             net::wait_traits<
253                 std::chrono::steady_clock>,
254             Executor> timer; // rate timer;
255 #else
256         net::steady_timer timer;
257 #endif
258         int waiting = 0;
259
260         impl_type(impl_type&&) = default;
261
262         template<class... Args>
263         explicit
264         impl_type(std::false_type, Args&&...);
265
266         template<class RatePolicy_, class... Args>
267         explicit
268         impl_type(std::true_type,
269             RatePolicy_&& policy, Args&&...);
270
271         impl_type& operator=(impl_type&&) = delete;
272
273         beast::executor_type<socket_type>
274         ex() noexcept
275         {
276             return this->socket.get_executor();
277         }
278
279         RatePolicy&
280         policy() noexcept
281         {
282             return this->boost::empty_value<RatePolicy>::get();
283         }
284
285         RatePolicy const&
286         policy() const noexcept
287         {
288             return this->boost::empty_value<RatePolicy>::get();
289         }
290
291         template<class Executor2>
292         void on_timer(Executor2 const& ex2);
293
294         void reset();       // set timeouts to never
295         void close();       // cancel everything
296     };
297
298     // We use shared ownership for the state so it can
299     // outlive the destruction of the stream_socket object,
300     // in the case where there is no outstanding read or write
301     // but the implementation is still waiting on a timer.
302     boost::shared_ptr<impl_type> impl_;
303
304     template<class Executor2>
305     struct timeout_handler;
306
307     struct ops;
308
309 #if ! BOOST_BEAST_DOXYGEN
310     // boost::asio::ssl::stream needs these
311     // DEPRECATED
312     template<class>
313     friend class boost::asio::ssl::stream;
314     // DEPRECATED
315     using lowest_layer_type = socket_type;
316     // DEPRECATED
317     lowest_layer_type&
318     lowest_layer() noexcept
319     {
320         return impl_->socket;
321     }
322     // DEPRECATED
323     lowest_layer_type const&
324     lowest_layer() const noexcept
325     {
326         return impl_->socket;
327     }
328 #endif
329
330 public:
331     /** Destructor
332
333         This function destroys the stream, cancelling any outstanding
334         asynchronous operations associated with the socket as if by
335         calling cancel.
336     */
337     ~basic_stream();
338
339     /** Constructor
340
341         This constructor creates the stream by forwarding all arguments
342         to the underlying socket. The socket then needs to be open and
343         connected or accepted before data can be sent or received on it.
344
345         @param args A list of parameters forwarded to the constructor of
346         the underlying socket.
347     */
348 #if BOOST_BEAST_DOXYGEN
349     template<class... Args>
350     explicit
351     basic_stream(Args&&... args);
352 #else
353     template<class Arg0, class... Args,
354         class = typename std::enable_if<
355         ! std::is_constructible<RatePolicy, Arg0>::value>::type>
356     explicit
357     basic_stream(Arg0&& argo, Args&&... args);
358 #endif
359
360     /** Constructor
361
362         This constructor creates the stream with the specified rate
363         policy, and forwards all remaining arguments to the underlying
364         socket. The socket then needs to be open and connected or
365         accepted before data can be sent or received on it.
366
367         @param policy The rate policy object to use. The stream will
368         take ownership of this object by decay-copy.
369
370         @param args A list of parameters forwarded to the constructor of
371         the underlying socket.
372     */
373 #if BOOST_BEAST_DOXYGEN
374     template<class RatePolicy_, class... Args>
375     explicit
376     basic_stream(RatePolicy_&& policy, Args&&... args);
377 #else
378     template<class RatePolicy_, class Arg0, class... Args,
379         class = typename std::enable_if<
380             std::is_constructible<
381                 RatePolicy, RatePolicy_>::value>::type>
382     basic_stream(
383         RatePolicy_&& policy, Arg0&& arg, Args&&... args);
384 #endif
385
386     /** Move constructor
387
388         @param other The other object from which the move will occur.
389
390         @note Following the move, the moved-from object is in the
391         same state as if newly constructed.
392     */
393     basic_stream(basic_stream&& other);
394
395     /// Move assignment (deleted).
396     basic_stream& operator=(basic_stream&&) = delete;
397
398     /// Return a reference to the underlying socket
399     socket_type&
400     socket() noexcept
401     {
402         return impl_->socket;
403     }
404
405     /// Return a reference to the underlying socket
406     socket_type const&
407     socket() const noexcept
408     {
409         return impl_->socket;
410     }
411
412     /** Release ownership of the underlying socket.
413
414         This function causes all outstanding asynchronous connect,
415         read, and write operations to be canceled as if by a call
416         to @ref cancel. Ownership of the underlying socket is then
417         transferred to the caller.
418     */
419     socket_type
420     release_socket();
421
422     //--------------------------------------------------------------------------
423
424     /// Returns the rate policy associated with the object
425     RatePolicy&
426     rate_policy() noexcept
427     {
428         return impl_->policy();
429     }
430
431     /// Returns the rate policy associated with the object
432     RatePolicy const&
433     rate_policy() const noexcept
434     {
435         return impl_->policy();
436     }
437
438     /** Set the timeout for the next logical operation.
439
440         This sets either the read timer, the write timer, or
441         both timers to expire after the specified amount of time
442         has elapsed. If a timer expires when the corresponding
443         asynchronous operation is outstanding, the stream will be
444         closed and any outstanding operations will complete with the
445         error @ref beast::error::timeout. Otherwise, if the timer
446         expires while no operations are outstanding, and the expiraton
447         is not set again, the next operation will time out immediately.
448
449         The timer applies collectively to any asynchronous reads
450         or writes initiated after the expiration is set, until the
451         expiration is set again. A call to @ref async_connect
452         counts as both a read and a write.
453
454         @param expiry_time The amount of time after which a logical
455         operation should be considered timed out.
456     */
457     void
458     expires_after(
459         std::chrono::nanoseconds expiry_time);
460
461     /** Set the timeout for the next logical operation.
462
463         This sets either the read timer, the write timer, or both
464         timers to expire at the specified time point. If a timer
465         expires when the corresponding asynchronous operation is
466         outstanding, the stream will be closed and any outstanding
467         operations will complete with the error @ref beast::error::timeout.
468         Otherwise, if the timer expires while no operations are outstanding,
469         and the expiraton is not set again, the next operation will time out
470         immediately.
471
472         The timer applies collectively to any asynchronous reads
473         or writes initiated after the expiration is set, until the
474         expiration is set again. A call to @ref async_connect
475         counts as both a read and a write.
476
477         @param expiry_time The time point after which a logical
478         operation should be considered timed out.
479     */
480     void
481     expires_at(net::steady_timer::time_point expiry_time);
482
483     /// Disable the timeout for the next logical operation.
484     void
485     expires_never();
486
487     /** Cancel all asynchronous operations associated with the socket.
488
489         This function causes all outstanding asynchronous connect,
490         read, and write operations to finish immediately. Completion
491         handlers for cancelled operations will receive the error
492         `net::error::operation_aborted`. Completion handlers not
493         yet invoked whose operations have completed, will receive
494         the error corresponding to the result of the operation (which
495         may indicate success).
496     */
497     void
498     cancel();
499
500     /** Close the timed stream.
501
502         This cancels all of the outstanding asynchronous operations
503         as if by calling @ref cancel, and closes the underlying socket.
504     */
505     void
506     close();
507
508     //--------------------------------------------------------------------------
509
510     /** Get the executor associated with the object.
511
512         This function may be used to obtain the executor object that the
513         stream uses to dispatch completion handlers without an assocaited
514         executor.
515
516         @return A copy of the executor that stream will use to dispatch handlers.
517     */
518     executor_type
519     get_executor() noexcept
520     {
521         return impl_->ex();
522     }
523
524     /** Connect the stream to the specified endpoint.
525
526         This function is used to connect the underlying socket to the
527         specified remote endpoint. The function call will block until
528         the connection is successfully made or an error occurs.
529         The underlying socket is automatically opened if needed.
530         An automatically opened socket is not returned to the
531         closed state upon failure.
532
533         @param ep The remote endpoint to connect to.
534
535         @throws system_error Thrown on failure.
536
537         @see connect
538     */
539     void
540     connect(endpoint_type const& ep)
541     {
542         socket().connect(ep);
543     }
544
545     /** Connect the stream to the specified endpoint.
546
547         This function is used to connect the underlying socket to the
548         specified remote endpoint. The function call will block until
549         the connection is successfully made or an error occurs.
550         The underlying socket is automatically opened if needed.
551         An automatically opened socket is not returned to the
552         closed state upon failure.
553
554         @param ep The remote endpoint to connect to.
555
556         @param ec Set to indicate what error occurred, if any.
557
558         @see connect
559     */
560     void
561     connect(endpoint_type const& ep, error_code& ec)
562     {
563         socket().connect(ep, ec);
564     }
565
566     /** Establishes a connection by trying each endpoint in a sequence.
567
568         This function attempts to connect the stream to one of a sequence of
569         endpoints by trying each endpoint until a connection is successfully
570         established.
571         The underlying socket is automatically opened if needed.
572         An automatically opened socket is not returned to the
573         closed state upon failure.
574
575         The algorithm, known as a <em>composed operation</em>, is implemented
576         in terms of calls to the underlying socket's `connect` function.
577
578         @param endpoints A sequence of endpoints.
579
580         @returns The successfully connected endpoint.
581
582         @throws system_error Thrown on failure. If the sequence is
583         empty, the associated error code is `net::error::not_found`.
584         Otherwise, contains the error from the last connection attempt.
585     */
586     template<class EndpointSequence
587     #if ! BOOST_BEAST_DOXYGEN
588         ,class = typename std::enable_if<
589             net::is_endpoint_sequence<
590                 EndpointSequence>::value>::type
591     #endif
592     >
593     typename Protocol::endpoint
594     connect(EndpointSequence const& endpoints)
595     {
596         return net::connect(socket(), endpoints);
597     }
598
599     /** Establishes a connection by trying each endpoint in a sequence.
600
601         This function attempts to connect the stream to one of a sequence of
602         endpoints by trying each endpoint until a connection is successfully
603         established.
604         The underlying socket is automatically opened if needed.
605         An automatically opened socket is not returned to the
606         closed state upon failure.
607
608         The algorithm, known as a <em>composed operation</em>, is implemented
609         in terms of calls to the underlying socket's `connect` function.
610
611         @param endpoints A sequence of endpoints.
612
613         @param ec Set to indicate what error occurred, if any. If the sequence is
614         empty, set to `net::error::not_found`. Otherwise, contains the error
615         from the last connection attempt.
616
617         @returns On success, the successfully connected endpoint. Otherwise, a
618         default-constructed endpoint.
619     */
620     template<class EndpointSequence
621     #if ! BOOST_BEAST_DOXYGEN
622         ,class = typename std::enable_if<
623             net::is_endpoint_sequence<
624                 EndpointSequence>::value>::type
625     #endif
626     >
627     typename Protocol::endpoint
628     connect(
629         EndpointSequence const& endpoints,
630         error_code& ec
631     )
632     {
633         return net::connect(socket(), endpoints, ec);
634     }
635
636     /** Establishes a connection by trying each endpoint in a sequence.
637
638         This function attempts to connect the stream to one of a sequence of
639         endpoints by trying each endpoint until a connection is successfully
640         established.
641         The underlying socket is automatically opened if needed.
642         An automatically opened socket is not returned to the
643         closed state upon failure.
644
645         The algorithm, known as a <em>composed operation</em>, is implemented
646         in terms of calls to the underlying socket's `connect` function.
647
648         @param begin An iterator pointing to the start of a sequence of endpoints.
649
650         @param end An iterator pointing to the end of a sequence of endpoints.
651
652         @returns An iterator denoting the successfully connected endpoint.
653
654         @throws system_error Thrown on failure. If the sequence is
655         empty, the associated error code is `net::error::not_found`.
656         Otherwise, contains the error from the last connection attempt.
657     */
658     template<class Iterator>
659     Iterator
660     connect(
661         Iterator begin, Iterator end)
662     {
663         return net::connect(socket(), begin, end);
664     }
665
666     /** Establishes a connection by trying each endpoint in a sequence.
667
668         This function attempts to connect the stream to one of a sequence of
669         endpoints by trying each endpoint until a connection is successfully
670         established.
671         The underlying socket is automatically opened if needed.
672         An automatically opened socket is not returned to the
673         closed state upon failure.
674
675         The algorithm, known as a <em>composed operation</em>, is implemented
676         in terms of calls to the underlying socket's `connect` function.
677
678         @param begin An iterator pointing to the start of a sequence of endpoints.
679
680         @param end An iterator pointing to the end of a sequence of endpoints.
681
682         @param ec Set to indicate what error occurred, if any. If the sequence is
683         empty, set to boost::asio::error::not_found. Otherwise, contains the error
684         from the last connection attempt.
685
686         @returns On success, an iterator denoting the successfully connected
687         endpoint. Otherwise, the end iterator.
688     */
689     template<class Iterator>
690     Iterator
691     connect(
692         Iterator begin, Iterator end,
693         error_code& ec)
694     {
695         return net::connect(socket(), begin, end, ec);
696     }
697
698     /** Establishes a connection by trying each endpoint in a sequence.
699
700         This function attempts to connect the stream to one of a sequence of
701         endpoints by trying each endpoint until a connection is successfully
702         established.
703         The underlying socket is automatically opened if needed.
704         An automatically opened socket is not returned to the
705         closed state upon failure.
706
707         The algorithm, known as a <em>composed operation</em>, is implemented
708         in terms of calls to the underlying socket's `connect` function.
709
710         @param endpoints A sequence of endpoints.
711
712         @param connect_condition A function object that is called prior to each
713         connection attempt. The signature of the function object must be:
714         @code
715         bool connect_condition(
716             error_code const& ec,
717             typename Protocol::endpoint const& next);
718         @endcode
719         The @c ec parameter contains the result from the most recent connect
720         operation. Before the first connection attempt, @c ec is always set to
721         indicate success. The @c next parameter is the next endpoint to be tried.
722         The function object should return true if the next endpoint should be tried,
723         and false if it should be skipped.
724
725         @returns The successfully connected endpoint.
726
727         @throws boost::system::system_error Thrown on failure. If the sequence is
728         empty, the associated error code is `net::error::not_found`.
729         Otherwise, contains the error from the last connection attempt.
730     */
731     template<
732         class EndpointSequence, class ConnectCondition
733     #if ! BOOST_BEAST_DOXYGEN
734         ,class = typename std::enable_if<
735             net::is_endpoint_sequence<
736                 EndpointSequence>::value>::type
737     #endif
738     >
739     typename Protocol::endpoint
740     connect(
741         EndpointSequence const& endpoints,
742         ConnectCondition connect_condition
743     )
744     {
745         return net::connect(socket(), endpoints, connect_condition);
746     }
747
748     /** Establishes a connection by trying each endpoint in a sequence.
749
750         This function attempts to connect the stream to one of a sequence of
751         endpoints by trying each endpoint until a connection is successfully
752         established.
753         The underlying socket is automatically opened if needed.
754         An automatically opened socket is not returned to the
755         closed state upon failure.
756
757         The algorithm, known as a <em>composed operation</em>, is implemented
758         in terms of calls to the underlying socket's `connect` function.
759
760         @param endpoints A sequence of endpoints.
761
762         @param connect_condition A function object that is called prior to each
763         connection attempt. The signature of the function object must be:
764         @code
765         bool connect_condition(
766             error_code const& ec,
767             typename Protocol::endpoint const& next);
768         @endcode
769         The @c ec parameter contains the result from the most recent connect
770         operation. Before the first connection attempt, @c ec is always set to
771         indicate success. The @c next parameter is the next endpoint to be tried.
772         The function object should return true if the next endpoint should be tried,
773         and false if it should be skipped.
774
775         @param ec Set to indicate what error occurred, if any. If the sequence is
776         empty, set to `net::error::not_found`. Otherwise, contains the error
777         from the last connection attempt.
778
779         @returns On success, the successfully connected endpoint. Otherwise, a
780         default-constructed endpoint.
781     */
782     template<
783         class EndpointSequence, class ConnectCondition
784     #if ! BOOST_BEAST_DOXYGEN
785         ,class = typename std::enable_if<
786             net::is_endpoint_sequence<
787                 EndpointSequence>::value>::type
788     #endif
789     >
790     typename Protocol::endpoint
791     connect(
792         EndpointSequence const& endpoints,
793         ConnectCondition connect_condition,
794         error_code& ec)
795     {
796         return net::connect(socket(), endpoints, connect_condition, ec);
797     }
798
799     /** Establishes a connection by trying each endpoint in a sequence.
800
801         This function attempts to connect the stream to one of a sequence of
802         endpoints by trying each endpoint until a connection is successfully
803         established.
804         The underlying socket is automatically opened if needed.
805         An automatically opened socket is not returned to the
806         closed state upon failure.
807
808         The algorithm, known as a <em>composed operation</em>, is implemented
809         in terms of calls to the underlying socket's `connect` function.
810
811         @param begin An iterator pointing to the start of a sequence of endpoints.
812
813         @param end An iterator pointing to the end of a sequence of endpoints.
814
815         @param connect_condition A function object that is called prior to each
816         connection attempt. The signature of the function object must be:
817         @code
818         bool connect_condition(
819             error_code const& ec,
820             typename Protocol::endpoint const& next);
821         @endcode
822         The @c ec parameter contains the result from the most recent connect
823         operation. Before the first connection attempt, @c ec is always set to
824         indicate success. The @c next parameter is the next endpoint to be tried.
825         The function object should return true if the next endpoint should be tried,
826         and false if it should be skipped.
827
828         @returns An iterator denoting the successfully connected endpoint.
829
830         @throws boost::system::system_error Thrown on failure. If the sequence is
831         empty, the associated @c error_code is `net::error::not_found`.
832         Otherwise, contains the error from the last connection attempt.
833     */
834     template<
835         class Iterator, class ConnectCondition>
836     Iterator
837     connect(
838         Iterator begin, Iterator end,
839         ConnectCondition connect_condition)
840     {
841         return net::connect(socket(), begin, end, connect_condition);
842     }
843
844     /** Establishes a connection by trying each endpoint in a sequence.
845
846         This function attempts to connect the stream to one of a sequence of
847         endpoints by trying each endpoint until a connection is successfully
848         established.
849         The underlying socket is automatically opened if needed.
850         An automatically opened socket is not returned to the
851         closed state upon failure.
852
853         The algorithm, known as a <em>composed operation</em>, is implemented
854         in terms of calls to the underlying socket's `connect` function.
855
856         @param begin An iterator pointing to the start of a sequence of endpoints.
857
858         @param end An iterator pointing to the end of a sequence of endpoints.
859
860         @param connect_condition A function object that is called prior to each
861         connection attempt. The signature of the function object must be:
862         @code
863         bool connect_condition(
864             error_code const& ec,
865             typename Protocol::endpoint const& next);
866         @endcode
867         The @c ec parameter contains the result from the most recent connect
868         operation. Before the first connection attempt, @c ec is always set to
869         indicate success. The @c next parameter is the next endpoint to be tried.
870         The function object should return true if the next endpoint should be tried,
871         and false if it should be skipped.
872
873         @param ec Set to indicate what error occurred, if any. If the sequence is
874         empty, set to `net::error::not_found`. Otherwise, contains the error
875         from the last connection attempt.
876
877         @returns On success, an iterator denoting the successfully connected
878         endpoint. Otherwise, the end iterator.
879     */
880     template<
881         class Iterator, class ConnectCondition>
882     Iterator
883     connect(
884         Iterator begin, Iterator end,
885         ConnectCondition connect_condition,
886         error_code& ec)
887     {
888         return net::connect(socket(), begin, end, connect_condition, ec);
889     }
890
891     /** Connect the stream to the specified endpoint asynchronously.
892
893         This function is used to asynchronously connect the underlying
894         socket to the specified remote endpoint. The function call always
895         returns immediately.
896         The underlying socket is automatically opened if needed.
897         An automatically opened socket is not returned to the
898         closed state upon failure.
899
900         If the timeout timer expires while the operation is outstanding,
901         the operation will be canceled and the completion handler will be
902         invoked with the error @ref error::timeout.
903
904         @param ep The remote endpoint to which the underlying socket will be
905         connected. Copies will be made of the endpoint object as required.
906
907         @param handler The completion handler to invoke when the operation
908         completes. The implementation takes ownership of the handler by
909         performing a decay-copy. The equivalent function signature of
910         the handler must be:
911         @code
912         void handler(
913             error_code ec         // Result of operation
914         );
915         @endcode
916         Regardless of whether the asynchronous operation completes
917         immediately or not, the handler will not be invoked from within
918         this function. Invocation of the handler will be performed in a
919         manner equivalent to using `net::post`.
920
921         @see async_connect
922     */
923     template<
924         BOOST_BEAST_ASYNC_TPARAM1 ConnectHandler =
925             net::default_completion_token_t<executor_type>
926     >
927     BOOST_BEAST_ASYNC_RESULT1(ConnectHandler)
928     async_connect(
929         endpoint_type const& ep,
930         ConnectHandler&& handler =
931             net::default_completion_token_t<
932                 executor_type>{});
933
934     /** Establishes a connection by trying each endpoint in a sequence asynchronously.
935
936         This function attempts to connect the stream to one of a sequence of
937         endpoints by trying each endpoint until a connection is successfully
938         established.
939         The underlying socket is automatically opened if needed.
940         An automatically opened socket is not returned to the
941         closed state upon failure.
942
943         The algorithm, known as a <em>composed asynchronous operation</em>, is
944         implemented in terms of calls to the underlying socket's `async_connect`
945         function.
946
947         If the timeout timer expires while the operation is outstanding,
948         the current connection attempt will be canceled and the completion
949         handler will be invoked with the error @ref error::timeout.
950
951         @param endpoints A sequence of endpoints. This this object must meet
952         the requirements of <em>EndpointSequence</em>.
953
954         @param handler The completion handler to invoke when the operation
955         completes. The implementation takes ownership of the handler by
956         performing a decay-copy. The equivalent function signature of
957         the handler must be:
958         @code
959         void handler(
960             // Result of operation. if the sequence is empty, set to
961             // net::error::not_found. Otherwise, contains the
962             // error from the last connection attempt.
963             error_code const& error,
964
965             // On success, the successfully connected endpoint.
966             // Otherwise, a default-constructed endpoint.
967             typename Protocol::endpoint const& endpoint
968         );
969         @endcode
970         Regardless of whether the asynchronous operation completes
971         immediately or not, the handler will not be invoked from within
972         this function. Invocation of the handler will be performed in a
973         manner equivalent to using `net::post`.
974     */
975     template<
976         class EndpointSequence,
977         BOOST_ASIO_COMPLETION_TOKEN_FOR(
978             void(error_code, typename Protocol::endpoint))
979             RangeConnectHandler =
980                 net::default_completion_token_t<executor_type>
981     #if ! BOOST_BEAST_DOXYGEN
982         ,class = typename std::enable_if<
983             net::is_endpoint_sequence<
984                 EndpointSequence>::value>::type
985     #endif
986     >
987     BOOST_ASIO_INITFN_RESULT_TYPE(
988         RangeConnectHandler,
989         void(error_code, typename Protocol::endpoint))
990     async_connect(
991         EndpointSequence const& endpoints,
992         RangeConnectHandler&& handler =
993             net::default_completion_token_t<executor_type>{});
994
995     /** Establishes a connection by trying each endpoint in a sequence asynchronously.
996
997         This function attempts to connect the stream to one of a sequence of
998         endpoints by trying each endpoint until a connection is successfully
999         established.
1000         The underlying socket is automatically opened if needed.
1001         An automatically opened socket is not returned to the
1002         closed state upon failure.
1003
1004         The algorithm, known as a <em>composed asynchronous operation</em>, is
1005         implemented in terms of calls to the underlying socket's `async_connect`
1006         function.
1007
1008         If the timeout timer expires while the operation is outstanding,
1009         the current connection attempt will be canceled and the completion
1010         handler will be invoked with the error @ref error::timeout.
1011
1012         @param endpoints A sequence of endpoints. This this object must meet
1013         the requirements of <em>EndpointSequence</em>.
1014
1015         @param connect_condition A function object that is called prior to each
1016         connection attempt. The signature of the function object must be:
1017         @code
1018         bool connect_condition(
1019             error_code const& ec,
1020             typename Protocol::endpoint const& next);
1021         @endcode
1022         The @c ec parameter contains the result from the most recent connect
1023         operation. Before the first connection attempt, @c ec is always set to
1024         indicate success. The @c next parameter is the next endpoint to be tried.
1025         The function object should return true if the next endpoint should be tried,
1026         and false if it should be skipped.
1027
1028         @param handler The completion handler to invoke when the operation
1029         completes. The implementation takes ownership of the handler by
1030         performing a decay-copy. The equivalent function signature of
1031         the handler must be:
1032         @code
1033         void handler(
1034             // Result of operation. if the sequence is empty, set to
1035             // net::error::not_found. Otherwise, contains the
1036             // error from the last connection attempt.
1037             error_code const& error,
1038
1039             // On success, the successfully connected endpoint.
1040             // Otherwise, a default-constructed endpoint.
1041             typename Protocol::endpoint const& endpoint
1042         );
1043         @endcode
1044         Regardless of whether the asynchronous operation completes
1045         immediately or not, the handler will not be invoked from within
1046         this function. Invocation of the handler will be performed in a
1047         manner equivalent to using `net::post`.
1048
1049         @par Example
1050         The following connect condition function object can be used to output
1051         information about the individual connection attempts:
1052         @code
1053         struct my_connect_condition
1054         {
1055             bool operator()(
1056                 error_code const& ec,
1057                 net::ip::tcp::endpoint const& next)
1058             {
1059                 if (ec)
1060                     std::cout << "Error: " << ec.message() << std::endl;
1061                 std::cout << "Trying: " << next << std::endl;
1062                 return true;
1063             }
1064         };
1065         @endcode
1066     */
1067     template<
1068         class EndpointSequence,
1069         class ConnectCondition,
1070         BOOST_ASIO_COMPLETION_TOKEN_FOR(
1071             void(error_code, typename Protocol::endpoint))
1072             RangeConnectHandler =
1073                 net::default_completion_token_t<executor_type>
1074     #if ! BOOST_BEAST_DOXYGEN
1075         ,class = typename std::enable_if<
1076             net::is_endpoint_sequence<
1077                 EndpointSequence>::value>::type
1078     #endif
1079     >
1080     BOOST_ASIO_INITFN_RESULT_TYPE(
1081         RangeConnectHandler,
1082         void(error_code, typename Protocol::endpoint))
1083     async_connect(
1084         EndpointSequence const& endpoints,
1085         ConnectCondition connect_condition,
1086         RangeConnectHandler&& handler =
1087             net::default_completion_token_t<
1088                 executor_type>{});
1089
1090     /** Establishes a connection by trying each endpoint in a sequence asynchronously.
1091
1092         This function attempts to connect the stream to one of a sequence of
1093         endpoints by trying each endpoint until a connection is successfully
1094         established.
1095         The underlying socket is automatically opened if needed.
1096         An automatically opened socket is not returned to the
1097         closed state upon failure.
1098
1099         The algorithm, known as a <em>composed asynchronous operation</em>, is
1100         implemented in terms of calls to the underlying socket's `async_connect`
1101         function.
1102
1103         If the timeout timer expires while the operation is outstanding,
1104         the current connection attempt will be canceled and the completion
1105         handler will be invoked with the error @ref error::timeout.
1106
1107         @param begin An iterator pointing to the start of a sequence of endpoints.
1108
1109         @param end An iterator pointing to the end of a sequence of endpoints.
1110
1111         @param handler The completion handler to invoke when the operation
1112         completes. The implementation takes ownership of the handler by
1113         performing a decay-copy. The equivalent function signature of
1114         the handler must be:
1115         @code
1116         void handler(
1117             // Result of operation. if the sequence is empty, set to
1118             // net::error::not_found. Otherwise, contains the
1119             // error from the last connection attempt.
1120             error_code const& error,
1121
1122             // On success, an iterator denoting the successfully
1123             // connected endpoint. Otherwise, the end iterator.
1124             Iterator iterator
1125         );
1126         @endcode
1127         Regardless of whether the asynchronous operation completes
1128         immediately or not, the handler will not be invoked from within
1129         this function. Invocation of the handler will be performed in a
1130         manner equivalent to using `net::post`.
1131     */
1132     template<
1133         class Iterator,
1134         BOOST_ASIO_COMPLETION_TOKEN_FOR(
1135             void(error_code, Iterator))
1136             IteratorConnectHandler =
1137                 net::default_completion_token_t<executor_type>>
1138     BOOST_ASIO_INITFN_RESULT_TYPE(
1139         IteratorConnectHandler,
1140         void(error_code, Iterator))
1141     async_connect(
1142         Iterator begin, Iterator end,
1143         IteratorConnectHandler&& handler =
1144             net::default_completion_token_t<executor_type>{});
1145
1146     /** Establishes a connection by trying each endpoint in a sequence asynchronously.
1147
1148         This function attempts to connect the stream to one of a sequence of
1149         endpoints by trying each endpoint until a connection is successfully
1150         established.
1151         The algorithm, known as a <em>composed asynchronous operation</em>, is
1152         implemented in terms of calls to the underlying socket's `async_connect`
1153         function.
1154
1155         If the timeout timer expires while the operation is outstanding,
1156         the current connection attempt will be canceled and the completion
1157         handler will be invoked with the error @ref error::timeout.
1158
1159         @param begin An iterator pointing to the start of a sequence of endpoints.
1160
1161         @param end An iterator pointing to the end of a sequence of endpoints.
1162
1163         @param connect_condition A function object that is called prior to each
1164         connection attempt. The signature of the function object must be:
1165         @code
1166         bool connect_condition(
1167             error_code const& ec,
1168             Iterator next);
1169         @endcode
1170
1171         @param handler The completion handler to invoke when the operation
1172         completes. The implementation takes ownership of the handler by
1173         performing a decay-copy. The equivalent function signature of
1174         the handler must be:
1175         @code
1176         void handler(
1177             // Result of operation. if the sequence is empty, set to
1178             // net::error::not_found. Otherwise, contains the
1179             // error from the last connection attempt.
1180             error_code const& error,
1181
1182             // On success, an iterator denoting the successfully
1183             // connected endpoint. Otherwise, the end iterator.
1184             Iterator iterator
1185         );
1186         @endcode
1187         Regardless of whether the asynchronous operation completes
1188         immediately or not, the handler will not be invoked from within
1189         this function. Invocation of the handler will be performed in a
1190         manner equivalent to using `net::post`.
1191     */
1192     template<
1193         class Iterator,
1194         class ConnectCondition,
1195         BOOST_ASIO_COMPLETION_TOKEN_FOR(
1196             void(error_code, Iterator))
1197             IteratorConnectHandler =
1198                 net::default_completion_token_t<executor_type>>
1199     BOOST_ASIO_INITFN_RESULT_TYPE(
1200         IteratorConnectHandler,
1201         void(error_code, Iterator))
1202     async_connect(
1203         Iterator begin, Iterator end,
1204         ConnectCondition connect_condition,
1205         IteratorConnectHandler&& handler =
1206             net::default_completion_token_t<executor_type>{});
1207
1208     //--------------------------------------------------------------------------
1209
1210     /** Read some data.
1211
1212         This function is used to read some data from the stream.
1213
1214         The call blocks until one of the following is true:
1215
1216         @li One or more bytes are read from the stream.
1217
1218         @li An error occurs.
1219
1220         @param buffers The buffers into which the data will be read. If the
1221         size of the buffers is zero bytes, the call always returns
1222         immediately with no error.
1223
1224         @returns The number of bytes read.
1225
1226         @throws system_error Thrown on failure.
1227
1228         @note The `read_some` operation may not receive all of the requested
1229         number of bytes. Consider using the function `net::read` if you need
1230         to ensure that the requested amount of data is read before the
1231         blocking operation completes.
1232     */
1233     template<class MutableBufferSequence>
1234     std::size_t
1235     read_some(MutableBufferSequence const& buffers)
1236     {
1237         return impl_->socket.read_some(buffers);
1238     }
1239
1240     /** Read some data.
1241
1242         This function is used to read some data from the underlying socket.
1243
1244         The call blocks until one of the following is true:
1245
1246         @li One or more bytes are read from the stream.
1247
1248         @li An error occurs.
1249
1250         @param buffers The buffers into which the data will be read. If the
1251         size of the buffers is zero bytes, the call always returns
1252         immediately with no error.
1253
1254         @param ec Set to indicate what error occurred, if any.
1255
1256         @returns The number of bytes read.
1257
1258         @note The `read_some` operation may not receive all of the requested
1259         number of bytes. Consider using the function `net::read` if you need
1260         to ensure that the requested amount of data is read before the
1261         blocking operation completes.
1262     */
1263     template<class MutableBufferSequence>
1264     std::size_t
1265     read_some(
1266         MutableBufferSequence const& buffers,
1267         error_code& ec)
1268     {
1269         return impl_->socket.read_some(buffers, ec);
1270     }
1271
1272     /** Read some data asynchronously.
1273
1274         This function is used to asynchronously read data from the stream.
1275
1276         This call always returns immediately. The asynchronous operation
1277         will continue until one of the following conditions is true:
1278
1279         @li One or more bytes are read from the stream.
1280
1281         @li An error occurs.
1282
1283         The algorithm, known as a <em>composed asynchronous operation</em>,
1284         is implemented in terms of calls to the next layer's `async_read_some`
1285         function. The program must ensure that no other calls to @ref read_some
1286         or @ref async_read_some are performed until this operation completes.
1287
1288         If the timeout timer expires while the operation is outstanding,
1289         the operation will be canceled and the completion handler will be
1290         invoked with the error @ref error::timeout.
1291
1292         @param buffers The buffers into which the data will be read. If the size
1293         of the buffers is zero bytes, the operation always completes immediately
1294         with no error.
1295         Although the buffers object may be copied as necessary, ownership of the
1296         underlying memory blocks is retained by the caller, which must guarantee
1297         that they remain valid until the handler is called.
1298
1299         @param handler The completion handler to invoke when the operation
1300         completes. The implementation takes ownership of the handler by
1301         performing a decay-copy. The equivalent function signature of
1302         the handler must be:
1303         @code
1304         void handler(
1305             error_code error,               // Result of operation.
1306             std::size_t bytes_transferred   // Number of bytes read.
1307         );
1308         @endcode
1309         Regardless of whether the asynchronous operation completes
1310         immediately or not, the handler will not be invoked from within
1311         this function. Invocation of the handler will be performed in a
1312         manner equivalent to using `net::post`.
1313
1314         @note The `async_read_some` operation may not receive all of the requested
1315         number of bytes. Consider using the function `net::async_read` if you need
1316         to ensure that the requested amount of data is read before the asynchronous
1317         operation completes.
1318     */
1319     template<
1320         class MutableBufferSequence,
1321         BOOST_BEAST_ASYNC_TPARAM2 ReadHandler =
1322             net::default_completion_token_t<executor_type>
1323     >
1324     BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
1325     async_read_some(
1326         MutableBufferSequence const& buffers,
1327         ReadHandler&& handler =
1328             net::default_completion_token_t<executor_type>{}
1329     );
1330
1331     /** Write some data.
1332
1333         This function is used to write some data to the stream.
1334
1335         The call blocks until one of the following is true:
1336
1337         @li One or more bytes are written to the stream.
1338
1339         @li An error occurs.
1340
1341         @param buffers The buffers from which the data will be written. If the
1342         size of the buffers is zero bytes, the call always returns immediately
1343         with no error.
1344
1345         @returns The number of bytes written.
1346
1347         @throws system_error Thrown on failure.
1348
1349         @note The `write_some` operation may not transmit all of the requested
1350         number of bytes. Consider using the function `net::write` if you need
1351         to ensure that the requested amount of data is written before the
1352         blocking operation completes.
1353     */
1354     template<class ConstBufferSequence>
1355     std::size_t
1356     write_some(ConstBufferSequence const& buffers)
1357     {
1358         return impl_->socket.write_some(buffers);
1359     }
1360
1361     /** Write some data.
1362
1363         This function is used to write some data to the stream.
1364
1365         The call blocks until one of the following is true:
1366
1367         @li One or more bytes are written to the stream.
1368
1369         @li An error occurs.
1370
1371         @param buffers The buffers from which the data will be written. If the
1372         size of the buffers is zero bytes, the call always returns immediately
1373         with no error.
1374
1375         @param ec Set to indicate what error occurred, if any.
1376
1377         @returns The number of bytes written.
1378
1379         @throws system_error Thrown on failure.
1380
1381         @note The `write_some` operation may not transmit all of the requested
1382         number of bytes. Consider using the function `net::write` if you need
1383         to ensure that the requested amount of data is written before the
1384         blocking operation completes.
1385     */
1386     template<class ConstBufferSequence>
1387     std::size_t
1388     write_some(
1389         ConstBufferSequence const& buffers,
1390         error_code& ec)
1391     {
1392         return impl_->socket.write_some(buffers, ec);
1393     }
1394
1395     /** Write some data asynchronously.
1396
1397         This function is used to asynchronously write data to the underlying socket.
1398
1399         This call always returns immediately. The asynchronous operation
1400         will continue until one of the following conditions is true:
1401
1402         @li One or more bytes are written to the stream.
1403
1404         @li An error occurs.
1405
1406         The algorithm, known as a <em>composed asynchronous operation</em>,
1407         is implemented in terms of calls to the next layer's `async_write_some`
1408         function. The program must ensure that no other calls to @ref async_write_some
1409         are performed until this operation completes.
1410
1411         If the timeout timer expires while the operation is outstanding,
1412         the operation will be canceled and the completion handler will be
1413         invoked with the error @ref error::timeout.
1414
1415         @param buffers The buffers from which the data will be written. If the
1416         size of the buffers is zero bytes, the operation  always completes
1417         immediately with no error.
1418         Although the buffers object may be copied as necessary, ownership of the
1419         underlying memory blocks is retained by the caller, which must guarantee
1420         that they remain valid until the handler is called.
1421
1422         @param handler The completion handler to invoke when the operation
1423         completes. The implementation takes ownership of the handler by
1424         performing a decay-copy. The equivalent function signature of
1425         the handler must be:
1426         @code
1427         void handler(
1428             error_code error,               // Result of operation.
1429             std::size_t bytes_transferred   // Number of bytes written.
1430         );
1431         @endcode
1432         Regardless of whether the asynchronous operation completes
1433         immediately or not, the handler will not be invoked from within
1434         this function. Invocation of the handler will be performed in a
1435         manner equivalent to using `net::post`.
1436
1437         @note The `async_write_some` operation may not transmit all of the requested
1438         number of bytes. Consider using the function `net::async_write` if you need
1439         to ensure that the requested amount of data is sent before the asynchronous
1440         operation completes.
1441     */
1442     template<
1443         class ConstBufferSequence,
1444         BOOST_BEAST_ASYNC_TPARAM2 WriteHandler =
1445             net::default_completion_token_t<Executor>
1446     >
1447     BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
1448     async_write_some(
1449         ConstBufferSequence const& buffers,
1450         WriteHandler&& handler =
1451             net::default_completion_token_t<Executor>{});
1452 };
1453
1454 } // beast
1455 } // boost
1456
1457 #include <boost/beast/core/impl/basic_stream.hpp>
1458
1459 #endif