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::any_io_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::any_io_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;
237 net::is_executor<Executor>::value || net::execution::is_executor<Executor>::value,
238 "Executor type requirements not met");
241 : boost::enable_shared_from_this<impl_type>
242 , boost::empty_value<RatePolicy>
245 net::basic_stream_socket<
246 Protocol, Executor> socket;
251 net::basic_waitable_timer<
252 std::chrono::steady_clock,
254 std::chrono::steady_clock>,
255 Executor> timer; // rate timer;
257 net::steady_timer timer;
261 impl_type(impl_type&&) = default;
263 template<class... Args>
265 impl_type(std::false_type, Args&&...);
267 template<class RatePolicy_, class... Args>
269 impl_type(std::true_type,
270 RatePolicy_&& policy, Args&&...);
272 impl_type& operator=(impl_type&&) = delete;
274 beast::executor_type<socket_type>
277 return this->socket.get_executor();
283 return this->boost::empty_value<RatePolicy>::get();
287 policy() const noexcept
289 return this->boost::empty_value<RatePolicy>::get();
292 template<class Executor2>
293 void on_timer(Executor2 const& ex2);
295 void reset(); // set timeouts to never
296 void close() noexcept; // cancel everything
299 // We use shared ownership for the state so it can
300 // outlive the destruction of the stream_socket object,
301 // in the case where there is no outstanding read or write
302 // but the implementation is still waiting on a timer.
303 boost::shared_ptr<impl_type> impl_;
305 template<class Executor2>
306 struct timeout_handler;
310 #if ! BOOST_BEAST_DOXYGEN
311 // boost::asio::ssl::stream needs these
314 friend class boost::asio::ssl::stream;
316 using lowest_layer_type = socket_type;
319 lowest_layer() noexcept
321 return impl_->socket;
324 lowest_layer_type const&
325 lowest_layer() const noexcept
327 return impl_->socket;
334 This function destroys the stream, cancelling any outstanding
335 asynchronous operations associated with the socket as if by
342 This constructor creates the stream by forwarding all arguments
343 to the underlying socket. The socket then needs to be open and
344 connected or accepted before data can be sent or received on it.
346 @param args A list of parameters forwarded to the constructor of
347 the underlying socket.
349 #if BOOST_BEAST_DOXYGEN
350 template<class... Args>
352 basic_stream(Args&&... args);
354 template<class Arg0, class... Args,
355 class = typename std::enable_if<
356 ! std::is_constructible<RatePolicy, Arg0>::value>::type>
358 basic_stream(Arg0&& argo, Args&&... args);
363 This constructor creates the stream with the specified rate
364 policy, and forwards all remaining arguments to the underlying
365 socket. The socket then needs to be open and connected or
366 accepted before data can be sent or received on it.
368 @param policy The rate policy object to use. The stream will
369 take ownership of this object by decay-copy.
371 @param args A list of parameters forwarded to the constructor of
372 the underlying socket.
374 #if BOOST_BEAST_DOXYGEN
375 template<class RatePolicy_, class... Args>
377 basic_stream(RatePolicy_&& policy, Args&&... args);
379 template<class RatePolicy_, class Arg0, class... Args,
380 class = typename std::enable_if<
381 std::is_constructible<
382 RatePolicy, RatePolicy_>::value>::type>
384 RatePolicy_&& policy, Arg0&& arg, Args&&... args);
389 @param other The other object from which the move will occur.
391 @note Following the move, the moved-from object is in the
392 same state as if newly constructed.
394 basic_stream(basic_stream&& other);
396 /// Move assignment (deleted).
397 basic_stream& operator=(basic_stream&&) = delete;
399 /// Return a reference to the underlying socket
403 return impl_->socket;
406 /// Return a reference to the underlying socket
408 socket() const noexcept
410 return impl_->socket;
413 /** Release ownership of the underlying socket.
415 This function causes all outstanding asynchronous connect,
416 read, and write operations to be canceled as if by a call
417 to @ref cancel. Ownership of the underlying socket is then
418 transferred to the caller.
423 //--------------------------------------------------------------------------
425 /// Returns the rate policy associated with the object
427 rate_policy() noexcept
429 return impl_->policy();
432 /// Returns the rate policy associated with the object
434 rate_policy() const noexcept
436 return impl_->policy();
439 /** Set the timeout for the next logical operation.
441 This sets either the read timer, the write timer, or
442 both timers to expire after the specified amount of time
443 has elapsed. If a timer expires when the corresponding
444 asynchronous operation is outstanding, the stream will be
445 closed and any outstanding operations will complete with the
446 error @ref beast::error::timeout. Otherwise, if the timer
447 expires while no operations are outstanding, and the expiraton
448 is not set again, the next operation will time out immediately.
450 The timer applies collectively to any asynchronous reads
451 or writes initiated after the expiration is set, until the
452 expiration is set again. A call to @ref async_connect
453 counts as both a read and a write.
455 @param expiry_time The amount of time after which a logical
456 operation should be considered timed out.
460 net::steady_timer::duration expiry_time);
462 /** Set the timeout for the next logical operation.
464 This sets either the read timer, the write timer, or both
465 timers to expire at the specified time point. If a timer
466 expires when the corresponding asynchronous operation is
467 outstanding, the stream will be closed and any outstanding
468 operations will complete with the error @ref beast::error::timeout.
469 Otherwise, if the timer expires while no operations are outstanding,
470 and the expiraton is not set again, the next operation will time out
473 The timer applies collectively to any asynchronous reads
474 or writes initiated after the expiration is set, until the
475 expiration is set again. A call to @ref async_connect
476 counts as both a read and a write.
478 @param expiry_time The time point after which a logical
479 operation should be considered timed out.
482 expires_at(net::steady_timer::time_point expiry_time);
484 /// Disable the timeout for the next logical operation.
488 /** Cancel all asynchronous operations associated with the socket.
490 This function causes all outstanding asynchronous connect,
491 read, and write operations to finish immediately. Completion
492 handlers for cancelled operations will receive the error
493 `net::error::operation_aborted`. Completion handlers not
494 yet invoked whose operations have completed, will receive
495 the error corresponding to the result of the operation (which
496 may indicate success).
501 /** Close the timed stream.
503 This cancels all of the outstanding asynchronous operations
504 as if by calling @ref cancel, and closes the underlying socket.
509 //--------------------------------------------------------------------------
511 /** Get the executor associated with the object.
513 This function may be used to obtain the executor object that the
514 stream uses to dispatch completion handlers without an assocaited
517 @return A copy of the executor that stream will use to dispatch handlers.
520 get_executor() noexcept
525 /** Connect the stream to the specified endpoint.
527 This function is used to connect the underlying socket to the
528 specified remote endpoint. The function call will block until
529 the connection is successfully made or an error occurs.
530 The underlying socket is automatically opened if needed.
531 An automatically opened socket is not returned to the
532 closed state upon failure.
534 @param ep The remote endpoint to connect to.
536 @throws system_error Thrown on failure.
541 connect(endpoint_type const& ep)
543 socket().connect(ep);
546 /** Connect the stream to the specified endpoint.
548 This function is used to connect the underlying socket to the
549 specified remote endpoint. The function call will block until
550 the connection is successfully made or an error occurs.
551 The underlying socket is automatically opened if needed.
552 An automatically opened socket is not returned to the
553 closed state upon failure.
555 @param ep The remote endpoint to connect to.
557 @param ec Set to indicate what error occurred, if any.
562 connect(endpoint_type const& ep, error_code& ec)
564 socket().connect(ep, ec);
567 /** Establishes a connection by trying each endpoint in a sequence.
569 This function attempts to connect the stream to one of a sequence of
570 endpoints by trying each endpoint until a connection is successfully
572 The underlying socket is automatically opened if needed.
573 An automatically opened socket is not returned to the
574 closed state upon failure.
576 The algorithm, known as a <em>composed operation</em>, is implemented
577 in terms of calls to the underlying socket's `connect` function.
579 @param endpoints A sequence of endpoints.
581 @returns The successfully connected endpoint.
583 @throws system_error Thrown on failure. If the sequence is
584 empty, the associated error code is `net::error::not_found`.
585 Otherwise, contains the error from the last connection attempt.
587 template<class EndpointSequence
588 #if ! BOOST_BEAST_DOXYGEN
589 ,class = typename std::enable_if<
590 net::is_endpoint_sequence<
591 EndpointSequence>::value>::type
594 typename Protocol::endpoint
595 connect(EndpointSequence const& endpoints)
597 return net::connect(socket(), endpoints);
600 /** Establishes a connection by trying each endpoint in a sequence.
602 This function attempts to connect the stream to one of a sequence of
603 endpoints by trying each endpoint until a connection is successfully
605 The underlying socket is automatically opened if needed.
606 An automatically opened socket is not returned to the
607 closed state upon failure.
609 The algorithm, known as a <em>composed operation</em>, is implemented
610 in terms of calls to the underlying socket's `connect` function.
612 @param endpoints A sequence of endpoints.
614 @param ec Set to indicate what error occurred, if any. If the sequence is
615 empty, set to `net::error::not_found`. Otherwise, contains the error
616 from the last connection attempt.
618 @returns On success, the successfully connected endpoint. Otherwise, a
619 default-constructed endpoint.
621 template<class EndpointSequence
622 #if ! BOOST_BEAST_DOXYGEN
623 ,class = typename std::enable_if<
624 net::is_endpoint_sequence<
625 EndpointSequence>::value>::type
628 typename Protocol::endpoint
630 EndpointSequence const& endpoints,
634 return net::connect(socket(), endpoints, ec);
637 /** Establishes a connection by trying each endpoint in a sequence.
639 This function attempts to connect the stream to one of a sequence of
640 endpoints by trying each endpoint until a connection is successfully
642 The underlying socket is automatically opened if needed.
643 An automatically opened socket is not returned to the
644 closed state upon failure.
646 The algorithm, known as a <em>composed operation</em>, is implemented
647 in terms of calls to the underlying socket's `connect` function.
649 @param begin An iterator pointing to the start of a sequence of endpoints.
651 @param end An iterator pointing to the end of a sequence of endpoints.
653 @returns An iterator denoting the successfully connected endpoint.
655 @throws system_error Thrown on failure. If the sequence is
656 empty, the associated error code is `net::error::not_found`.
657 Otherwise, contains the error from the last connection attempt.
659 template<class Iterator>
662 Iterator begin, Iterator end)
664 return net::connect(socket(), begin, end);
667 /** Establishes a connection by trying each endpoint in a sequence.
669 This function attempts to connect the stream to one of a sequence of
670 endpoints by trying each endpoint until a connection is successfully
672 The underlying socket is automatically opened if needed.
673 An automatically opened socket is not returned to the
674 closed state upon failure.
676 The algorithm, known as a <em>composed operation</em>, is implemented
677 in terms of calls to the underlying socket's `connect` function.
679 @param begin An iterator pointing to the start of a sequence of endpoints.
681 @param end An iterator pointing to the end of a sequence of endpoints.
683 @param ec Set to indicate what error occurred, if any. If the sequence is
684 empty, set to boost::asio::error::not_found. Otherwise, contains the error
685 from the last connection attempt.
687 @returns On success, an iterator denoting the successfully connected
688 endpoint. Otherwise, the end iterator.
690 template<class Iterator>
693 Iterator begin, Iterator end,
696 return net::connect(socket(), begin, end, ec);
699 /** Establishes a connection by trying each endpoint in a sequence.
701 This function attempts to connect the stream to one of a sequence of
702 endpoints by trying each endpoint until a connection is successfully
704 The underlying socket is automatically opened if needed.
705 An automatically opened socket is not returned to the
706 closed state upon failure.
708 The algorithm, known as a <em>composed operation</em>, is implemented
709 in terms of calls to the underlying socket's `connect` function.
711 @param endpoints A sequence of endpoints.
713 @param connect_condition A function object that is called prior to each
714 connection attempt. The signature of the function object must be:
716 bool connect_condition(
717 error_code const& ec,
718 typename Protocol::endpoint const& next);
720 The @c ec parameter contains the result from the most recent connect
721 operation. Before the first connection attempt, @c ec is always set to
722 indicate success. The @c next parameter is the next endpoint to be tried.
723 The function object should return true if the next endpoint should be tried,
724 and false if it should be skipped.
726 @returns The successfully connected endpoint.
728 @throws boost::system::system_error Thrown on failure. If the sequence is
729 empty, the associated error code is `net::error::not_found`.
730 Otherwise, contains the error from the last connection attempt.
733 class EndpointSequence, class ConnectCondition
734 #if ! BOOST_BEAST_DOXYGEN
735 ,class = typename std::enable_if<
736 net::is_endpoint_sequence<
737 EndpointSequence>::value>::type
740 typename Protocol::endpoint
742 EndpointSequence const& endpoints,
743 ConnectCondition connect_condition
746 return net::connect(socket(), endpoints, connect_condition);
749 /** Establishes a connection by trying each endpoint in a sequence.
751 This function attempts to connect the stream to one of a sequence of
752 endpoints by trying each endpoint until a connection is successfully
754 The underlying socket is automatically opened if needed.
755 An automatically opened socket is not returned to the
756 closed state upon failure.
758 The algorithm, known as a <em>composed operation</em>, is implemented
759 in terms of calls to the underlying socket's `connect` function.
761 @param endpoints A sequence of endpoints.
763 @param connect_condition A function object that is called prior to each
764 connection attempt. The signature of the function object must be:
766 bool connect_condition(
767 error_code const& ec,
768 typename Protocol::endpoint const& next);
770 The @c ec parameter contains the result from the most recent connect
771 operation. Before the first connection attempt, @c ec is always set to
772 indicate success. The @c next parameter is the next endpoint to be tried.
773 The function object should return true if the next endpoint should be tried,
774 and false if it should be skipped.
776 @param ec Set to indicate what error occurred, if any. If the sequence is
777 empty, set to `net::error::not_found`. Otherwise, contains the error
778 from the last connection attempt.
780 @returns On success, the successfully connected endpoint. Otherwise, a
781 default-constructed endpoint.
784 class EndpointSequence, class ConnectCondition
785 #if ! BOOST_BEAST_DOXYGEN
786 ,class = typename std::enable_if<
787 net::is_endpoint_sequence<
788 EndpointSequence>::value>::type
791 typename Protocol::endpoint
793 EndpointSequence const& endpoints,
794 ConnectCondition connect_condition,
797 return net::connect(socket(), endpoints, connect_condition, ec);
800 /** Establishes a connection by trying each endpoint in a sequence.
802 This function attempts to connect the stream to one of a sequence of
803 endpoints by trying each endpoint until a connection is successfully
805 The underlying socket is automatically opened if needed.
806 An automatically opened socket is not returned to the
807 closed state upon failure.
809 The algorithm, known as a <em>composed operation</em>, is implemented
810 in terms of calls to the underlying socket's `connect` function.
812 @param begin An iterator pointing to the start of a sequence of endpoints.
814 @param end An iterator pointing to the end of a sequence of endpoints.
816 @param connect_condition A function object that is called prior to each
817 connection attempt. The signature of the function object must be:
819 bool connect_condition(
820 error_code const& ec,
821 typename Protocol::endpoint const& next);
823 The @c ec parameter contains the result from the most recent connect
824 operation. Before the first connection attempt, @c ec is always set to
825 indicate success. The @c next parameter is the next endpoint to be tried.
826 The function object should return true if the next endpoint should be tried,
827 and false if it should be skipped.
829 @returns An iterator denoting the successfully connected endpoint.
831 @throws boost::system::system_error Thrown on failure. If the sequence is
832 empty, the associated @c error_code is `net::error::not_found`.
833 Otherwise, contains the error from the last connection attempt.
836 class Iterator, class ConnectCondition>
839 Iterator begin, Iterator end,
840 ConnectCondition connect_condition)
842 return net::connect(socket(), begin, end, connect_condition);
845 /** Establishes a connection by trying each endpoint in a sequence.
847 This function attempts to connect the stream to one of a sequence of
848 endpoints by trying each endpoint until a connection is successfully
850 The underlying socket is automatically opened if needed.
851 An automatically opened socket is not returned to the
852 closed state upon failure.
854 The algorithm, known as a <em>composed operation</em>, is implemented
855 in terms of calls to the underlying socket's `connect` function.
857 @param begin An iterator pointing to the start of a sequence of endpoints.
859 @param end An iterator pointing to the end of a sequence of endpoints.
861 @param connect_condition A function object that is called prior to each
862 connection attempt. The signature of the function object must be:
864 bool connect_condition(
865 error_code const& ec,
866 typename Protocol::endpoint const& next);
868 The @c ec parameter contains the result from the most recent connect
869 operation. Before the first connection attempt, @c ec is always set to
870 indicate success. The @c next parameter is the next endpoint to be tried.
871 The function object should return true if the next endpoint should be tried,
872 and false if it should be skipped.
874 @param ec Set to indicate what error occurred, if any. If the sequence is
875 empty, set to `net::error::not_found`. Otherwise, contains the error
876 from the last connection attempt.
878 @returns On success, an iterator denoting the successfully connected
879 endpoint. Otherwise, the end iterator.
882 class Iterator, class ConnectCondition>
885 Iterator begin, Iterator end,
886 ConnectCondition connect_condition,
889 return net::connect(socket(), begin, end, connect_condition, ec);
892 /** Connect the stream to the specified endpoint asynchronously.
894 This function is used to asynchronously connect the underlying
895 socket to the specified remote endpoint. The function call always
897 The underlying socket is automatically opened if needed.
898 An automatically opened socket is not returned to the
899 closed state upon failure.
901 If the timeout timer expires while the operation is outstanding,
902 the operation will be canceled and the completion handler will be
903 invoked with the error @ref error::timeout.
905 @param ep The remote endpoint to which the underlying socket will be
906 connected. Copies will be made of the endpoint object as required.
908 @param handler The completion handler to invoke when the operation
909 completes. The implementation takes ownership of the handler by
910 performing a decay-copy. The equivalent function signature of
914 error_code ec // Result of operation
917 Regardless of whether the asynchronous operation completes
918 immediately or not, the handler will not be invoked from within
919 this function. Invocation of the handler will be performed in a
920 manner equivalent to using `net::post`.
925 BOOST_BEAST_ASYNC_TPARAM1 ConnectHandler =
926 net::default_completion_token_t<executor_type>
928 BOOST_BEAST_ASYNC_RESULT1(ConnectHandler)
930 endpoint_type const& ep,
931 ConnectHandler&& handler =
932 net::default_completion_token_t<
935 /** Establishes a connection by trying each endpoint in a sequence asynchronously.
937 This function attempts to connect the stream to one of a sequence of
938 endpoints by trying each endpoint until a connection is successfully
940 The underlying socket is automatically opened if needed.
941 An automatically opened socket is not returned to the
942 closed state upon failure.
944 The algorithm, known as a <em>composed asynchronous operation</em>, is
945 implemented in terms of calls to the underlying socket's `async_connect`
948 If the timeout timer expires while the operation is outstanding,
949 the current connection attempt will be canceled and the completion
950 handler will be invoked with the error @ref error::timeout.
952 @param endpoints A sequence of endpoints. This this object must meet
953 the requirements of <em>EndpointSequence</em>.
955 @param handler The completion handler to invoke when the operation
956 completes. The implementation takes ownership of the handler by
957 performing a decay-copy. The equivalent function signature of
961 // Result of operation. if the sequence is empty, set to
962 // net::error::not_found. Otherwise, contains the
963 // error from the last connection attempt.
964 error_code const& error,
966 // On success, the successfully connected endpoint.
967 // Otherwise, a default-constructed endpoint.
968 typename Protocol::endpoint const& endpoint
971 Regardless of whether the asynchronous operation completes
972 immediately or not, the handler will not be invoked from within
973 this function. Invocation of the handler will be performed in a
974 manner equivalent to using `net::post`.
977 class EndpointSequence,
978 BOOST_ASIO_COMPLETION_TOKEN_FOR(
979 void(error_code, typename Protocol::endpoint))
980 RangeConnectHandler =
981 net::default_completion_token_t<executor_type>
982 #if ! BOOST_BEAST_DOXYGEN
983 ,class = typename std::enable_if<
984 net::is_endpoint_sequence<
985 EndpointSequence>::value>::type
988 BOOST_ASIO_INITFN_RESULT_TYPE(
990 void(error_code, typename Protocol::endpoint))
992 EndpointSequence const& endpoints,
993 RangeConnectHandler&& handler =
994 net::default_completion_token_t<executor_type>{});
996 /** Establishes a connection by trying each endpoint in a sequence asynchronously.
998 This function attempts to connect the stream to one of a sequence of
999 endpoints by trying each endpoint until a connection is successfully
1001 The underlying socket is automatically opened if needed.
1002 An automatically opened socket is not returned to the
1003 closed state upon failure.
1005 The algorithm, known as a <em>composed asynchronous operation</em>, is
1006 implemented in terms of calls to the underlying socket's `async_connect`
1009 If the timeout timer expires while the operation is outstanding,
1010 the current connection attempt will be canceled and the completion
1011 handler will be invoked with the error @ref error::timeout.
1013 @param endpoints A sequence of endpoints. This this object must meet
1014 the requirements of <em>EndpointSequence</em>.
1016 @param connect_condition A function object that is called prior to each
1017 connection attempt. The signature of the function object must be:
1019 bool connect_condition(
1020 error_code const& ec,
1021 typename Protocol::endpoint const& next);
1023 The @c ec parameter contains the result from the most recent connect
1024 operation. Before the first connection attempt, @c ec is always set to
1025 indicate success. The @c next parameter is the next endpoint to be tried.
1026 The function object should return true if the next endpoint should be tried,
1027 and false if it should be skipped.
1029 @param handler The completion handler to invoke when the operation
1030 completes. The implementation takes ownership of the handler by
1031 performing a decay-copy. The equivalent function signature of
1032 the handler must be:
1035 // Result of operation. if the sequence is empty, set to
1036 // net::error::not_found. Otherwise, contains the
1037 // error from the last connection attempt.
1038 error_code const& error,
1040 // On success, the successfully connected endpoint.
1041 // Otherwise, a default-constructed endpoint.
1042 typename Protocol::endpoint const& endpoint
1045 Regardless of whether the asynchronous operation completes
1046 immediately or not, the handler will not be invoked from within
1047 this function. Invocation of the handler will be performed in a
1048 manner equivalent to using `net::post`.
1051 The following connect condition function object can be used to output
1052 information about the individual connection attempts:
1054 struct my_connect_condition
1057 error_code const& ec,
1058 net::ip::tcp::endpoint const& next)
1061 std::cout << "Error: " << ec.message() << std::endl;
1062 std::cout << "Trying: " << next << std::endl;
1069 class EndpointSequence,
1070 class ConnectCondition,
1071 BOOST_ASIO_COMPLETION_TOKEN_FOR(
1072 void(error_code, typename Protocol::endpoint))
1073 RangeConnectHandler =
1074 net::default_completion_token_t<executor_type>
1075 #if ! BOOST_BEAST_DOXYGEN
1076 ,class = typename std::enable_if<
1077 net::is_endpoint_sequence<
1078 EndpointSequence>::value>::type
1081 BOOST_ASIO_INITFN_RESULT_TYPE(
1082 RangeConnectHandler,
1083 void(error_code, typename Protocol::endpoint))
1085 EndpointSequence const& endpoints,
1086 ConnectCondition connect_condition,
1087 RangeConnectHandler&& handler =
1088 net::default_completion_token_t<
1091 /** Establishes a connection by trying each endpoint in a sequence asynchronously.
1093 This function attempts to connect the stream to one of a sequence of
1094 endpoints by trying each endpoint until a connection is successfully
1096 The underlying socket is automatically opened if needed.
1097 An automatically opened socket is not returned to the
1098 closed state upon failure.
1100 The algorithm, known as a <em>composed asynchronous operation</em>, is
1101 implemented in terms of calls to the underlying socket's `async_connect`
1104 If the timeout timer expires while the operation is outstanding,
1105 the current connection attempt will be canceled and the completion
1106 handler will be invoked with the error @ref error::timeout.
1108 @param begin An iterator pointing to the start of a sequence of endpoints.
1110 @param end An iterator pointing to the end of a sequence of endpoints.
1112 @param handler The completion handler to invoke when the operation
1113 completes. The implementation takes ownership of the handler by
1114 performing a decay-copy. The equivalent function signature of
1115 the handler must be:
1118 // Result of operation. if the sequence is empty, set to
1119 // net::error::not_found. Otherwise, contains the
1120 // error from the last connection attempt.
1121 error_code const& error,
1123 // On success, an iterator denoting the successfully
1124 // connected endpoint. Otherwise, the end iterator.
1128 Regardless of whether the asynchronous operation completes
1129 immediately or not, the handler will not be invoked from within
1130 this function. Invocation of the handler will be performed in a
1131 manner equivalent to using `net::post`.
1135 BOOST_ASIO_COMPLETION_TOKEN_FOR(
1136 void(error_code, Iterator))
1137 IteratorConnectHandler =
1138 net::default_completion_token_t<executor_type>>
1139 BOOST_ASIO_INITFN_RESULT_TYPE(
1140 IteratorConnectHandler,
1141 void(error_code, Iterator))
1143 Iterator begin, Iterator end,
1144 IteratorConnectHandler&& handler =
1145 net::default_completion_token_t<executor_type>{});
1147 /** Establishes a connection by trying each endpoint in a sequence asynchronously.
1149 This function attempts to connect the stream to one of a sequence of
1150 endpoints by trying each endpoint until a connection is successfully
1152 The algorithm, known as a <em>composed asynchronous operation</em>, is
1153 implemented in terms of calls to the underlying socket's `async_connect`
1156 If the timeout timer expires while the operation is outstanding,
1157 the current connection attempt will be canceled and the completion
1158 handler will be invoked with the error @ref error::timeout.
1160 @param begin An iterator pointing to the start of a sequence of endpoints.
1162 @param end An iterator pointing to the end of a sequence of endpoints.
1164 @param connect_condition A function object that is called prior to each
1165 connection attempt. The signature of the function object must be:
1167 bool connect_condition(
1168 error_code const& ec,
1169 typename Protocol::endpoint const& next);
1172 @param handler The completion handler to invoke when the operation
1173 completes. The implementation takes ownership of the handler by
1174 performing a decay-copy. The equivalent function signature of
1175 the handler must be:
1178 // Result of operation. if the sequence is empty, set to
1179 // net::error::not_found. Otherwise, contains the
1180 // error from the last connection attempt.
1181 error_code const& error,
1183 // On success, an iterator denoting the successfully
1184 // connected endpoint. Otherwise, the end iterator.
1188 Regardless of whether the asynchronous operation completes
1189 immediately or not, the handler will not be invoked from within
1190 this function. Invocation of the handler will be performed in a
1191 manner equivalent to using `net::post`.
1195 class ConnectCondition,
1196 BOOST_ASIO_COMPLETION_TOKEN_FOR(
1197 void(error_code, Iterator))
1198 IteratorConnectHandler =
1199 net::default_completion_token_t<executor_type>>
1200 BOOST_ASIO_INITFN_RESULT_TYPE(
1201 IteratorConnectHandler,
1202 void(error_code, Iterator))
1204 Iterator begin, Iterator end,
1205 ConnectCondition connect_condition,
1206 IteratorConnectHandler&& handler =
1207 net::default_completion_token_t<executor_type>{});
1209 //--------------------------------------------------------------------------
1213 This function is used to read some data from the stream.
1215 The call blocks until one of the following is true:
1217 @li One or more bytes are read from the stream.
1219 @li An error occurs.
1221 @param buffers The buffers into which the data will be read. If the
1222 size of the buffers is zero bytes, the call always returns
1223 immediately with no error.
1225 @returns The number of bytes read.
1227 @throws system_error Thrown on failure.
1229 @note The `read_some` operation may not receive all of the requested
1230 number of bytes. Consider using the function `net::read` if you need
1231 to ensure that the requested amount of data is read before the
1232 blocking operation completes.
1234 template<class MutableBufferSequence>
1236 read_some(MutableBufferSequence const& buffers)
1238 return impl_->socket.read_some(buffers);
1243 This function is used to read some data from the underlying socket.
1245 The call blocks until one of the following is true:
1247 @li One or more bytes are read from the stream.
1249 @li An error occurs.
1251 @param buffers The buffers into which the data will be read. If the
1252 size of the buffers is zero bytes, the call always returns
1253 immediately with no error.
1255 @param ec Set to indicate what error occurred, if any.
1257 @returns The number of bytes read.
1259 @note The `read_some` operation may not receive all of the requested
1260 number of bytes. Consider using the function `net::read` if you need
1261 to ensure that the requested amount of data is read before the
1262 blocking operation completes.
1264 template<class MutableBufferSequence>
1267 MutableBufferSequence const& buffers,
1270 return impl_->socket.read_some(buffers, ec);
1273 /** Read some data asynchronously.
1275 This function is used to asynchronously read data from the stream.
1277 This call always returns immediately. The asynchronous operation
1278 will continue until one of the following conditions is true:
1280 @li One or more bytes are read from the stream.
1282 @li An error occurs.
1284 The algorithm, known as a <em>composed asynchronous operation</em>,
1285 is implemented in terms of calls to the next layer's `async_read_some`
1286 function. The program must ensure that no other calls to @ref read_some
1287 or @ref async_read_some are performed until this operation completes.
1289 If the timeout timer expires while the operation is outstanding,
1290 the operation will be canceled and the completion handler will be
1291 invoked with the error @ref error::timeout.
1293 @param buffers The buffers into which the data will be read. If the size
1294 of the buffers is zero bytes, the operation always completes immediately
1296 Although the buffers object may be copied as necessary, ownership of the
1297 underlying memory blocks is retained by the caller, which must guarantee
1298 that they remain valid until the handler is called.
1300 @param handler The completion handler to invoke when the operation
1301 completes. The implementation takes ownership of the handler by
1302 performing a decay-copy. The equivalent function signature of
1303 the handler must be:
1306 error_code error, // Result of operation.
1307 std::size_t bytes_transferred // Number of bytes read.
1310 Regardless of whether the asynchronous operation completes
1311 immediately or not, the handler will not be invoked from within
1312 this function. Invocation of the handler will be performed in a
1313 manner equivalent to using `net::post`.
1315 @note The `async_read_some` operation may not receive all of the requested
1316 number of bytes. Consider using the function `net::async_read` if you need
1317 to ensure that the requested amount of data is read before the asynchronous
1318 operation completes.
1321 class MutableBufferSequence,
1322 BOOST_BEAST_ASYNC_TPARAM2 ReadHandler =
1323 net::default_completion_token_t<executor_type>
1325 BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
1327 MutableBufferSequence const& buffers,
1328 ReadHandler&& handler =
1329 net::default_completion_token_t<executor_type>{}
1332 /** Write some data.
1334 This function is used to write some data to the stream.
1336 The call blocks until one of the following is true:
1338 @li One or more bytes are written to the stream.
1340 @li An error occurs.
1342 @param buffers The buffers from which the data will be written. If the
1343 size of the buffers is zero bytes, the call always returns immediately
1346 @returns The number of bytes written.
1348 @throws system_error Thrown on failure.
1350 @note The `write_some` operation may not transmit all of the requested
1351 number of bytes. Consider using the function `net::write` if you need
1352 to ensure that the requested amount of data is written before the
1353 blocking operation completes.
1355 template<class ConstBufferSequence>
1357 write_some(ConstBufferSequence const& buffers)
1359 return impl_->socket.write_some(buffers);
1362 /** Write some data.
1364 This function is used to write some data to the stream.
1366 The call blocks until one of the following is true:
1368 @li One or more bytes are written to the stream.
1370 @li An error occurs.
1372 @param buffers The buffers from which the data will be written. If the
1373 size of the buffers is zero bytes, the call always returns immediately
1376 @param ec Set to indicate what error occurred, if any.
1378 @returns The number of bytes written.
1380 @throws system_error Thrown on failure.
1382 @note The `write_some` operation may not transmit all of the requested
1383 number of bytes. Consider using the function `net::write` if you need
1384 to ensure that the requested amount of data is written before the
1385 blocking operation completes.
1387 template<class ConstBufferSequence>
1390 ConstBufferSequence const& buffers,
1393 return impl_->socket.write_some(buffers, ec);
1396 /** Write some data asynchronously.
1398 This function is used to asynchronously write data to the underlying socket.
1400 This call always returns immediately. The asynchronous operation
1401 will continue until one of the following conditions is true:
1403 @li One or more bytes are written to the stream.
1405 @li An error occurs.
1407 The algorithm, known as a <em>composed asynchronous operation</em>,
1408 is implemented in terms of calls to the next layer's `async_write_some`
1409 function. The program must ensure that no other calls to @ref async_write_some
1410 are performed until this operation completes.
1412 If the timeout timer expires while the operation is outstanding,
1413 the operation will be canceled and the completion handler will be
1414 invoked with the error @ref error::timeout.
1416 @param buffers The buffers from which the data will be written. If the
1417 size of the buffers is zero bytes, the operation always completes
1418 immediately with no error.
1419 Although the buffers object may be copied as necessary, ownership of the
1420 underlying memory blocks is retained by the caller, which must guarantee
1421 that they remain valid until the handler is called.
1423 @param handler The completion handler to invoke when the operation
1424 completes. The implementation takes ownership of the handler by
1425 performing a decay-copy. The equivalent function signature of
1426 the handler must be:
1429 error_code error, // Result of operation.
1430 std::size_t bytes_transferred // Number of bytes written.
1433 Regardless of whether the asynchronous operation completes
1434 immediately or not, the handler will not be invoked from within
1435 this function. Invocation of the handler will be performed in a
1436 manner equivalent to using `net::post`.
1438 @note The `async_write_some` operation may not transmit all of the requested
1439 number of bytes. Consider using the function `net::async_write` if you need
1440 to ensure that the requested amount of data is sent before the asynchronous
1441 operation completes.
1444 class ConstBufferSequence,
1445 BOOST_BEAST_ASYNC_TPARAM2 WriteHandler =
1446 net::default_completion_token_t<Executor>
1448 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
1450 ConstBufferSequence const& buffers,
1451 WriteHandler&& handler =
1452 net::default_completion_token_t<Executor>{});
1458 #include <boost/beast/core/impl/basic_stream.hpp>