2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
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)
7 // Official repository: https://github.com/boostorg/beast
10 #ifndef BOOST_BEAST_CORE_BASIC_STREAM_HPP
11 #define BOOST_BEAST_CORE_BASIC_STREAM_HPP
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>
32 #if ! BOOST_BEAST_DOXYGEN
36 template<typename> class stream;
45 /** A stream socket wrapper with timeouts, an executor, and a rate limit policy.
47 This stream wraps a `net::basic_stream_socket` to provide
48 the following features:
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>.
55 @li Timeouts may be specified for each logical asynchronous operation
56 performing any reading, writing, or connecting.
58 @li A <em>RatePolicy</em> may be associated with the stream, to implement
59 rate limiting through the policy's interface.
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`.
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
77 @li Function objects submitted to the executor shall never run
78 concurrently with each other.
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.
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.
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
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.
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.
114 This function reads an HTTP request with a timeout, then sends the
115 HTTP response with a different timeout.
118 void process_http_1 (tcp_stream& stream, net::yield_context yield)
121 http::request<http::empty_body> req;
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);
127 // Calculate the response
128 http::response<http::string_body> res = make_response(req);
130 // Send the response, with a 30 second timeout.
131 stream.expires_after (std::chrono::seconds(30));
132 http::async_write (stream, res, yield);
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:
142 void process_http_2 (tcp_stream& stream, net::yield_context yield)
145 http::request<http::empty_body> req;
147 // Require that the read and write combined take no longer than 30 seconds
148 stream.expires_after(std::chrono::seconds(30));
150 http::async_read(stream, buffer, req, yield);
152 http::response<http::string_body> res = make_response(req);
153 http::async_write (stream, res, yield);
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
164 void do_ssl_handshake (net::ssl::stream<tcp_stream>& stream, net::yield_context yield)
166 // Require that the SSL handshake take no longer than 10 seconds
167 stream.expires_after(std::chrono::seconds(10));
169 stream.async_handshake(net::ssl::stream_base::client, yield);
175 Synchronous functions behave identically as that of the wrapped
176 `net::basic_stream_socket`. Timeouts are not available when performing
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`.
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`
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.
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>.
200 class Executor = net::executor,
201 class RatePolicy = unlimited_rate_policy
204 #if ! BOOST_BEAST_DOXYGEN
205 : private detail::stream_base
209 /// The type of the underlying socket.
211 net::basic_stream_socket<Protocol, Executor>;
213 /** The type of the executor associated with the stream.
215 This will be the type of executor used to invoke completion
216 handlers which do not have an explicit associated executor.
218 using executor_type = beast::executor_type<socket_type>;
220 /// Rebinds the stream type to another executor.
221 template<class Executor1>
222 struct rebind_executor
224 /// The stream type when rebound to the specified executor.
225 using other = basic_stream<
226 Protocol, Executor1, RatePolicy>;
229 /// The protocol type.
230 using protocol_type = Protocol;
232 /// The endpoint type.
233 using endpoint_type = typename Protocol::endpoint;
236 static_assert(net::is_executor<Executor>::value,
237 "Executor type requirements not met");
240 : boost::enable_shared_from_this<impl_type>
241 , boost::empty_value<RatePolicy>
244 net::basic_stream_socket<
245 Protocol, Executor> socket;
250 net::basic_waitable_timer<
251 std::chrono::steady_clock,
253 std::chrono::steady_clock>,
254 Executor> timer; // rate timer;
256 net::steady_timer timer;
260 impl_type(impl_type&&) = default;
262 template<class... Args>
264 impl_type(std::false_type, Args&&...);
266 template<class RatePolicy_, class... Args>
268 impl_type(std::true_type,
269 RatePolicy_&& policy, Args&&...);
271 impl_type& operator=(impl_type&&) = delete;
273 beast::executor_type<socket_type>
276 return this->socket.get_executor();
282 return this->boost::empty_value<RatePolicy>::get();
286 policy() const noexcept
288 return this->boost::empty_value<RatePolicy>::get();
291 template<class Executor2>
292 void on_timer(Executor2 const& ex2);
294 void reset(); // set timeouts to never
295 void close(); // cancel everything
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_;
304 template<class Executor2>
305 struct timeout_handler;
309 #if ! BOOST_BEAST_DOXYGEN
310 // boost::asio::ssl::stream needs these
313 friend class boost::asio::ssl::stream;
315 using lowest_layer_type = socket_type;
318 lowest_layer() noexcept
320 return impl_->socket;
323 lowest_layer_type const&
324 lowest_layer() const noexcept
326 return impl_->socket;
333 This function destroys the stream, cancelling any outstanding
334 asynchronous operations associated with the socket as if by
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.
345 @param args A list of parameters forwarded to the constructor of
346 the underlying socket.
348 #if BOOST_BEAST_DOXYGEN
349 template<class... Args>
351 basic_stream(Args&&... args);
353 template<class Arg0, class... Args,
354 class = typename std::enable_if<
355 ! std::is_constructible<RatePolicy, Arg0>::value>::type>
357 basic_stream(Arg0&& argo, Args&&... args);
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.
367 @param policy The rate policy object to use. The stream will
368 take ownership of this object by decay-copy.
370 @param args A list of parameters forwarded to the constructor of
371 the underlying socket.
373 #if BOOST_BEAST_DOXYGEN
374 template<class RatePolicy_, class... Args>
376 basic_stream(RatePolicy_&& policy, Args&&... args);
378 template<class RatePolicy_, class Arg0, class... Args,
379 class = typename std::enable_if<
380 std::is_constructible<
381 RatePolicy, RatePolicy_>::value>::type>
383 RatePolicy_&& policy, Arg0&& arg, Args&&... args);
388 @param other The other object from which the move will occur.
390 @note Following the move, the moved-from object is in the
391 same state as if newly constructed.
393 basic_stream(basic_stream&& other);
395 /// Move assignment (deleted).
396 basic_stream& operator=(basic_stream&&) = delete;
398 /// Return a reference to the underlying socket
402 return impl_->socket;
405 /// Return a reference to the underlying socket
407 socket() const noexcept
409 return impl_->socket;
412 /** Release ownership of the underlying socket.
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.
422 //--------------------------------------------------------------------------
424 /// Returns the rate policy associated with the object
426 rate_policy() noexcept
428 return impl_->policy();
431 /// Returns the rate policy associated with the object
433 rate_policy() const noexcept
435 return impl_->policy();
438 /** Set the timeout for the next logical operation.
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.
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.
454 @param expiry_time The amount of time after which a logical
455 operation should be considered timed out.
459 std::chrono::nanoseconds expiry_time);
461 /** Set the timeout for the next logical operation.
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
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.
477 @param expiry_time The time point after which a logical
478 operation should be considered timed out.
481 expires_at(net::steady_timer::time_point expiry_time);
483 /// Disable the timeout for the next logical operation.
487 /** Cancel all asynchronous operations associated with the socket.
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).
500 /** Close the timed stream.
502 This cancels all of the outstanding asynchronous operations
503 as if by calling @ref cancel, and closes the underlying socket.
508 //--------------------------------------------------------------------------
510 /** Get the executor associated with the object.
512 This function may be used to obtain the executor object that the
513 stream uses to dispatch completion handlers without an assocaited
516 @return A copy of the executor that stream will use to dispatch handlers.
519 get_executor() noexcept
524 /** Connect the stream to the specified endpoint.
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.
533 @param ep The remote endpoint to connect to.
535 @throws system_error Thrown on failure.
540 connect(endpoint_type const& ep)
542 socket().connect(ep);
545 /** Connect the stream to the specified endpoint.
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.
554 @param ep The remote endpoint to connect to.
556 @param ec Set to indicate what error occurred, if any.
561 connect(endpoint_type const& ep, error_code& ec)
563 socket().connect(ep, ec);
566 /** Establishes a connection by trying each endpoint in a sequence.
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
571 The underlying socket is automatically opened if needed.
572 An automatically opened socket is not returned to the
573 closed state upon failure.
575 The algorithm, known as a <em>composed operation</em>, is implemented
576 in terms of calls to the underlying socket's `connect` function.
578 @param endpoints A sequence of endpoints.
580 @returns The successfully connected endpoint.
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.
586 template<class EndpointSequence
587 #if ! BOOST_BEAST_DOXYGEN
588 ,class = typename std::enable_if<
589 net::is_endpoint_sequence<
590 EndpointSequence>::value>::type
593 typename Protocol::endpoint
594 connect(EndpointSequence const& endpoints)
596 return net::connect(socket(), endpoints);
599 /** Establishes a connection by trying each endpoint in a sequence.
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
604 The underlying socket is automatically opened if needed.
605 An automatically opened socket is not returned to the
606 closed state upon failure.
608 The algorithm, known as a <em>composed operation</em>, is implemented
609 in terms of calls to the underlying socket's `connect` function.
611 @param endpoints A sequence of endpoints.
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.
617 @returns On success, the successfully connected endpoint. Otherwise, a
618 default-constructed endpoint.
620 template<class EndpointSequence
621 #if ! BOOST_BEAST_DOXYGEN
622 ,class = typename std::enable_if<
623 net::is_endpoint_sequence<
624 EndpointSequence>::value>::type
627 typename Protocol::endpoint
629 EndpointSequence const& endpoints,
633 return net::connect(socket(), endpoints, ec);
636 /** Establishes a connection by trying each endpoint in a sequence.
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
641 The underlying socket is automatically opened if needed.
642 An automatically opened socket is not returned to the
643 closed state upon failure.
645 The algorithm, known as a <em>composed operation</em>, is implemented
646 in terms of calls to the underlying socket's `connect` function.
648 @param begin An iterator pointing to the start of a sequence of endpoints.
650 @param end An iterator pointing to the end of a sequence of endpoints.
652 @returns An iterator denoting the successfully connected endpoint.
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.
658 template<class Iterator>
661 Iterator begin, Iterator end)
663 return net::connect(socket(), begin, end);
666 /** Establishes a connection by trying each endpoint in a sequence.
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
671 The underlying socket is automatically opened if needed.
672 An automatically opened socket is not returned to the
673 closed state upon failure.
675 The algorithm, known as a <em>composed operation</em>, is implemented
676 in terms of calls to the underlying socket's `connect` function.
678 @param begin An iterator pointing to the start of a sequence of endpoints.
680 @param end An iterator pointing to the end of a sequence of endpoints.
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.
686 @returns On success, an iterator denoting the successfully connected
687 endpoint. Otherwise, the end iterator.
689 template<class Iterator>
692 Iterator begin, Iterator end,
695 return net::connect(socket(), begin, end, ec);
698 /** Establishes a connection by trying each endpoint in a sequence.
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
703 The underlying socket is automatically opened if needed.
704 An automatically opened socket is not returned to the
705 closed state upon failure.
707 The algorithm, known as a <em>composed operation</em>, is implemented
708 in terms of calls to the underlying socket's `connect` function.
710 @param endpoints A sequence of endpoints.
712 @param connect_condition A function object that is called prior to each
713 connection attempt. The signature of the function object must be:
715 bool connect_condition(
716 error_code const& ec,
717 typename Protocol::endpoint const& next);
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.
725 @returns The successfully connected endpoint.
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.
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
739 typename Protocol::endpoint
741 EndpointSequence const& endpoints,
742 ConnectCondition connect_condition
745 return net::connect(socket(), endpoints, connect_condition);
748 /** Establishes a connection by trying each endpoint in a sequence.
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
753 The underlying socket is automatically opened if needed.
754 An automatically opened socket is not returned to the
755 closed state upon failure.
757 The algorithm, known as a <em>composed operation</em>, is implemented
758 in terms of calls to the underlying socket's `connect` function.
760 @param endpoints A sequence of endpoints.
762 @param connect_condition A function object that is called prior to each
763 connection attempt. The signature of the function object must be:
765 bool connect_condition(
766 error_code const& ec,
767 typename Protocol::endpoint const& next);
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.
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.
779 @returns On success, the successfully connected endpoint. Otherwise, a
780 default-constructed endpoint.
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
790 typename Protocol::endpoint
792 EndpointSequence const& endpoints,
793 ConnectCondition connect_condition,
796 return net::connect(socket(), endpoints, connect_condition, ec);
799 /** Establishes a connection by trying each endpoint in a sequence.
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
804 The underlying socket is automatically opened if needed.
805 An automatically opened socket is not returned to the
806 closed state upon failure.
808 The algorithm, known as a <em>composed operation</em>, is implemented
809 in terms of calls to the underlying socket's `connect` function.
811 @param begin An iterator pointing to the start of a sequence of endpoints.
813 @param end An iterator pointing to the end of a sequence of endpoints.
815 @param connect_condition A function object that is called prior to each
816 connection attempt. The signature of the function object must be:
818 bool connect_condition(
819 error_code const& ec,
820 typename Protocol::endpoint const& next);
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.
828 @returns An iterator denoting the successfully connected endpoint.
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.
835 class Iterator, class ConnectCondition>
838 Iterator begin, Iterator end,
839 ConnectCondition connect_condition)
841 return net::connect(socket(), begin, end, connect_condition);
844 /** Establishes a connection by trying each endpoint in a sequence.
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
849 The underlying socket is automatically opened if needed.
850 An automatically opened socket is not returned to the
851 closed state upon failure.
853 The algorithm, known as a <em>composed operation</em>, is implemented
854 in terms of calls to the underlying socket's `connect` function.
856 @param begin An iterator pointing to the start of a sequence of endpoints.
858 @param end An iterator pointing to the end of a sequence of endpoints.
860 @param connect_condition A function object that is called prior to each
861 connection attempt. The signature of the function object must be:
863 bool connect_condition(
864 error_code const& ec,
865 typename Protocol::endpoint const& next);
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.
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.
877 @returns On success, an iterator denoting the successfully connected
878 endpoint. Otherwise, the end iterator.
881 class Iterator, class ConnectCondition>
884 Iterator begin, Iterator end,
885 ConnectCondition connect_condition,
888 return net::connect(socket(), begin, end, connect_condition, ec);
891 /** Connect the stream to the specified endpoint asynchronously.
893 This function is used to asynchronously connect the underlying
894 socket to the specified remote endpoint. The function call always
896 The underlying socket is automatically opened if needed.
897 An automatically opened socket is not returned to the
898 closed state upon failure.
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.
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.
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
913 error_code ec // Result of operation
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`.
924 BOOST_BEAST_ASYNC_TPARAM1 ConnectHandler =
925 net::default_completion_token_t<executor_type>
927 BOOST_BEAST_ASYNC_RESULT1(ConnectHandler)
929 endpoint_type const& ep,
930 ConnectHandler&& handler =
931 net::default_completion_token_t<
934 /** Establishes a connection by trying each endpoint in a sequence asynchronously.
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
939 The underlying socket is automatically opened if needed.
940 An automatically opened socket is not returned to the
941 closed state upon failure.
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`
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.
951 @param endpoints A sequence of endpoints. This this object must meet
952 the requirements of <em>EndpointSequence</em>.
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
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,
965 // On success, the successfully connected endpoint.
966 // Otherwise, a default-constructed endpoint.
967 typename Protocol::endpoint const& endpoint
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`.
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
987 BOOST_ASIO_INITFN_RESULT_TYPE(
989 void(error_code, typename Protocol::endpoint))
991 EndpointSequence const& endpoints,
992 RangeConnectHandler&& handler =
993 net::default_completion_token_t<executor_type>{});
995 /** Establishes a connection by trying each endpoint in a sequence asynchronously.
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
1000 The underlying socket is automatically opened if needed.
1001 An automatically opened socket is not returned to the
1002 closed state upon failure.
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`
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.
1012 @param endpoints A sequence of endpoints. This this object must meet
1013 the requirements of <em>EndpointSequence</em>.
1015 @param connect_condition A function object that is called prior to each
1016 connection attempt. The signature of the function object must be:
1018 bool connect_condition(
1019 error_code const& ec,
1020 typename Protocol::endpoint const& next);
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.
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:
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,
1039 // On success, the successfully connected endpoint.
1040 // Otherwise, a default-constructed endpoint.
1041 typename Protocol::endpoint const& endpoint
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`.
1050 The following connect condition function object can be used to output
1051 information about the individual connection attempts:
1053 struct my_connect_condition
1056 error_code const& ec,
1057 net::ip::tcp::endpoint const& next)
1060 std::cout << "Error: " << ec.message() << std::endl;
1061 std::cout << "Trying: " << next << std::endl;
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
1080 BOOST_ASIO_INITFN_RESULT_TYPE(
1081 RangeConnectHandler,
1082 void(error_code, typename Protocol::endpoint))
1084 EndpointSequence const& endpoints,
1085 ConnectCondition connect_condition,
1086 RangeConnectHandler&& handler =
1087 net::default_completion_token_t<
1090 /** Establishes a connection by trying each endpoint in a sequence asynchronously.
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
1095 The underlying socket is automatically opened if needed.
1096 An automatically opened socket is not returned to the
1097 closed state upon failure.
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`
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.
1107 @param begin An iterator pointing to the start of a sequence of endpoints.
1109 @param end An iterator pointing to the end of a sequence of endpoints.
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:
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,
1122 // On success, an iterator denoting the successfully
1123 // connected endpoint. Otherwise, the end iterator.
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`.
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))
1142 Iterator begin, Iterator end,
1143 IteratorConnectHandler&& handler =
1144 net::default_completion_token_t<executor_type>{});
1146 /** Establishes a connection by trying each endpoint in a sequence asynchronously.
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
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`
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.
1159 @param begin An iterator pointing to the start of a sequence of endpoints.
1161 @param end An iterator pointing to the end of a sequence of endpoints.
1163 @param connect_condition A function object that is called prior to each
1164 connection attempt. The signature of the function object must be:
1166 bool connect_condition(
1167 error_code const& ec,
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:
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,
1182 // On success, an iterator denoting the successfully
1183 // connected endpoint. Otherwise, the end iterator.
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`.
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))
1203 Iterator begin, Iterator end,
1204 ConnectCondition connect_condition,
1205 IteratorConnectHandler&& handler =
1206 net::default_completion_token_t<executor_type>{});
1208 //--------------------------------------------------------------------------
1212 This function is used to read some data from the stream.
1214 The call blocks until one of the following is true:
1216 @li One or more bytes are read from the stream.
1218 @li An error occurs.
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.
1224 @returns The number of bytes read.
1226 @throws system_error Thrown on failure.
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.
1233 template<class MutableBufferSequence>
1235 read_some(MutableBufferSequence const& buffers)
1237 return impl_->socket.read_some(buffers);
1242 This function is used to read some data from the underlying socket.
1244 The call blocks until one of the following is true:
1246 @li One or more bytes are read from the stream.
1248 @li An error occurs.
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.
1254 @param ec Set to indicate what error occurred, if any.
1256 @returns The number of bytes read.
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.
1263 template<class MutableBufferSequence>
1266 MutableBufferSequence const& buffers,
1269 return impl_->socket.read_some(buffers, ec);
1272 /** Read some data asynchronously.
1274 This function is used to asynchronously read data from the stream.
1276 This call always returns immediately. The asynchronous operation
1277 will continue until one of the following conditions is true:
1279 @li One or more bytes are read from the stream.
1281 @li An error occurs.
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.
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.
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
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.
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:
1305 error_code error, // Result of operation.
1306 std::size_t bytes_transferred // Number of bytes read.
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`.
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.
1320 class MutableBufferSequence,
1321 BOOST_BEAST_ASYNC_TPARAM2 ReadHandler =
1322 net::default_completion_token_t<executor_type>
1324 BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
1326 MutableBufferSequence const& buffers,
1327 ReadHandler&& handler =
1328 net::default_completion_token_t<executor_type>{}
1331 /** Write some data.
1333 This function is used to write some data to the stream.
1335 The call blocks until one of the following is true:
1337 @li One or more bytes are written to the stream.
1339 @li An error occurs.
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
1345 @returns The number of bytes written.
1347 @throws system_error Thrown on failure.
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.
1354 template<class ConstBufferSequence>
1356 write_some(ConstBufferSequence const& buffers)
1358 return impl_->socket.write_some(buffers);
1361 /** Write some data.
1363 This function is used to write some data to the stream.
1365 The call blocks until one of the following is true:
1367 @li One or more bytes are written to the stream.
1369 @li An error occurs.
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
1375 @param ec Set to indicate what error occurred, if any.
1377 @returns The number of bytes written.
1379 @throws system_error Thrown on failure.
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.
1386 template<class ConstBufferSequence>
1389 ConstBufferSequence const& buffers,
1392 return impl_->socket.write_some(buffers, ec);
1395 /** Write some data asynchronously.
1397 This function is used to asynchronously write data to the underlying socket.
1399 This call always returns immediately. The asynchronous operation
1400 will continue until one of the following conditions is true:
1402 @li One or more bytes are written to the stream.
1404 @li An error occurs.
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.
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.
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.
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:
1428 error_code error, // Result of operation.
1429 std::size_t bytes_transferred // Number of bytes written.
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`.
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.
1443 class ConstBufferSequence,
1444 BOOST_BEAST_ASYNC_TPARAM2 WriteHandler =
1445 net::default_completion_token_t<Executor>
1447 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
1449 ConstBufferSequence const& buffers,
1450 WriteHandler&& handler =
1451 net::default_completion_token_t<Executor>{});
1457 #include <boost/beast/core/impl/basic_stream.hpp>