]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/core/basic_stream.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / beast / core / basic_stream.hpp
1 //
2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/beast
8 //
9
10 #ifndef BOOST_BEAST_CORE_BASIC_STREAM_HPP
11 #define BOOST_BEAST_CORE_BASIC_STREAM_HPP
12
13 #include <boost/beast/core/detail/config.hpp>
14 #include <boost/beast/core/detail/stream_base.hpp>
15 #include <boost/beast/core/error.hpp>
16 #include <boost/beast/core/rate_policy.hpp>
17 #include <boost/beast/core/role.hpp>
18 #include <boost/beast/core/stream_traits.hpp>
19 #include <boost/asio/async_result.hpp>
20 #include <boost/asio/basic_stream_socket.hpp>
21 #include <boost/asio/connect.hpp>
22 #include <boost/asio/executor.hpp>
23 #include <boost/asio/is_executor.hpp>
24 #include <boost/core/empty_value.hpp>
25 #include <boost/config/workaround.hpp>
26 #include <boost/enable_shared_from_this.hpp>
27 #include <boost/shared_ptr.hpp>
28 #include <chrono>
29 #include <limits>
30 #include <memory>
31
32 #if ! BOOST_BEAST_DOXYGEN
33 namespace boost {
34 namespace asio {
35 namespace ssl {
36 template<typename> class stream;
37 } // ssl
38 } // asio
39 } // boost
40 #endif
41
42 namespace boost {
43 namespace beast {
44
45 /** A stream socket wrapper with timeouts, an executor, and a rate limit policy.
46
47 This stream wraps a `net::basic_stream_socket` to provide
48 the following features:
49
50 @li An <em>Executor</em> may be associated with the stream, which will
51 be used to invoke any completion handlers which do not already have
52 an associated executor. This achieves support for
53 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1322r0.html">[P1322R0] Networking TS enhancement to enable custom I/O executors</a>.
54
55 @li Timeouts may be specified for each logical asynchronous operation
56 performing any reading, writing, or connecting.
57
58 @li A <em>RatePolicy</em> may be associated with the stream, to implement
59 rate limiting through the policy's interface.
60
61 Although the stream supports multiple concurrent outstanding asynchronous
62 operations, the stream object is not thread-safe. The caller is responsible
63 for ensuring that the stream is accessed from only one thread at a time.
64 This includes the times when the stream, and its underlying socket, are
65 accessed by the networking implementation. To meet this thread safety
66 requirement, all asynchronous operations must be performed by the stream
67 within the same implicit strand (only one thread `net::io_context::run`)
68 or within the same explicit strand, such as an instance of `net::strand`.
69
70 Completion handlers with explicit associated executors (such as those
71 arising from use of `net::bind_executor`) will be invoked by the stream
72 using the associated executor. Otherwise, the completion handler will
73 be invoked by the executor associated with the stream upon construction.
74 The type of executor used with this stream must meet the following
75 requirements:
76
77 @li Function objects submitted to the executor shall never run
78 concurrently with each other.
79
80 The executor type `net::strand` meets these requirements. Use of a
81 strand as the executor in the stream class template offers an additional
82 notational convenience: the strand does not need to be specified in
83 each individual initiating function call.
84
85 Unlike other stream wrappers, the underlying socket is accessed
86 through the @ref socket member function instead of `next_layer`.
87 This causes the @ref basic_stream to be returned in calls
88 to @ref get_lowest_layer.
89
90 @par Usage
91
92 To use this stream declare an instance of the class. Then, before
93 each logical operation for which a timeout is desired, call
94 @ref expires_after with a duration, or call @ref expires_at with a
95 time point. Alternatively, call @ref expires_never to disable the
96 timeout for subsequent logical operations. A logical operation
97 is any series of one or more direct or indirect calls to the timeout
98 stream's asynchronous read, asynchronous write, or asynchronous connect
99 functions.
100
101 When a timeout is set and a mixed operation is performed (one that
102 includes both reads and writes, for example) the timeout applies
103 to all of the intermediate asynchronous operations used in the
104 enclosing operation. This allows timeouts to be applied to stream
105 algorithms which were not written specifically to allow for timeouts,
106 when those algorithms are passed a timeout stream with a timeout set.
107
108 When a timeout occurs the socket will be closed, canceling any
109 pending I/O operations. The completion handlers for these canceled
110 operations will be invoked with the error @ref beast::error::timeout.
111
112 @par Examples
113
114 This function reads an HTTP request with a timeout, then sends the
115 HTTP response with a different timeout.
116
117 @code
118 void process_http_1 (tcp_stream& stream, net::yield_context yield)
119 {
120 flat_buffer buffer;
121 http::request<http::empty_body> req;
122
123 // Read the request, with a 15 second timeout
124 stream.expires_after(std::chrono::seconds(15));
125 http::async_read(stream, buffer, req, yield);
126
127 // Calculate the response
128 http::response<http::string_body> res = make_response(req);
129
130 // Send the response, with a 30 second timeout.
131 stream.expires_after (std::chrono::seconds(30));
132 http::async_write (stream, res, yield);
133 }
134 @endcode
135
136 The example above could be expressed using a single timeout with a
137 simple modification. The function that follows first reads an HTTP
138 request then sends the HTTP response, with a single timeout that
139 applies to the entire combined operation of reading and writing:
140
141 @code
142 void process_http_2 (tcp_stream& stream, net::yield_context yield)
143 {
144 flat_buffer buffer;
145 http::request<http::empty_body> req;
146
147 // Require that the read and write combined take no longer than 30 seconds
148 stream.expires_after(std::chrono::seconds(30));
149
150 http::async_read(stream, buffer, req, yield);
151
152 http::response<http::string_body> res = make_response(req);
153 http::async_write (stream, res, yield);
154 }
155 @endcode
156
157 Some stream algorithms, such as `ssl::stream::async_handshake` perform
158 both reads and writes. A timeout set before calling the initiating function
159 of such composite stream algorithms will apply to the entire composite
160 operation. For example, a timeout may be set on performing the SSL handshake
161 thusly:
162
163 @code
164 void do_ssl_handshake (net::ssl::stream<tcp_stream>& stream, net::yield_context yield)
165 {
166 // Require that the SSL handshake take no longer than 10 seconds
167 stream.expires_after(std::chrono::seconds(10));
168
169 stream.async_handshake(net::ssl::stream_base::client, yield);
170 }
171 @endcode
172
173 @par Blocking I/O
174
175 Synchronous functions behave identically as that of the wrapped
176 `net::basic_stream_socket`. Timeouts are not available when performing
177 blocking calls.
178
179 @tparam Protocol A type meeting the requirements of <em>Protocol</em>
180 representing the protocol the protocol to use for the basic stream socket.
181 A common choice is `net::ip::tcp`.
182
183 @tparam Executor A type meeting the requirements of <em>Executor</em> to
184 be used for submitting all completion handlers which do not already have an
185 associated executor. If this type is omitted, the default of `net::any_io_executor`
186 will be used.
187
188 @par Thread Safety
189 <em>Distinct objects</em>: Safe.@n
190 <em>Shared objects</em>: Unsafe. The application must also ensure
191 that all asynchronous operations are performed within the same
192 implicit or explicit strand.
193
194 @see
195
196 @li <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1322r0.html">[P1322R0] Networking TS enhancement to enable custom I/O executors</a>.
197 */
198 template<
199 class Protocol,
200 class Executor = net::any_io_executor,
201 class RatePolicy = unlimited_rate_policy
202 >
203 class basic_stream
204 #if ! BOOST_BEAST_DOXYGEN
205 : private detail::stream_base
206 #endif
207 {
208 public:
209 /// The type of the underlying socket.
210 using socket_type =
211 net::basic_stream_socket<Protocol, Executor>;
212
213 /** The type of the executor associated with the stream.
214
215 This will be the type of executor used to invoke completion
216 handlers which do not have an explicit associated executor.
217 */
218 using executor_type = beast::executor_type<socket_type>;
219
220 /// Rebinds the stream type to another executor.
221 template<class Executor1>
222 struct rebind_executor
223 {
224 /// The stream type when rebound to the specified executor.
225 using other = basic_stream<
226 Protocol, Executor1, RatePolicy>;
227 };
228
229 /// The protocol type.
230 using protocol_type = Protocol;
231
232 /// The endpoint type.
233 using endpoint_type = typename Protocol::endpoint;
234
235 private:
236 static_assert(
237 net::is_executor<Executor>::value || net::execution::is_executor<Executor>::value,
238 "Executor type requirements not met");
239
240 struct impl_type
241 : boost::enable_shared_from_this<impl_type>
242 , boost::empty_value<RatePolicy>
243 {
244 // must come first
245 net::basic_stream_socket<
246 Protocol, Executor> socket;
247
248 op_state read;
249 op_state write;
250 #if 0
251 net::basic_waitable_timer<
252 std::chrono::steady_clock,
253 net::wait_traits<
254 std::chrono::steady_clock>,
255 Executor> timer; // rate timer;
256 #else
257 net::steady_timer timer;
258 #endif
259 int waiting = 0;
260
261 impl_type(impl_type&&) = default;
262
263 template<class... Args>
264 explicit
265 impl_type(std::false_type, Args&&...);
266
267 template<class RatePolicy_, class... Args>
268 explicit
269 impl_type(std::true_type,
270 RatePolicy_&& policy, Args&&...);
271
272 impl_type& operator=(impl_type&&) = delete;
273
274 beast::executor_type<socket_type>
275 ex() noexcept
276 {
277 return this->socket.get_executor();
278 }
279
280 RatePolicy&
281 policy() noexcept
282 {
283 return this->boost::empty_value<RatePolicy>::get();
284 }
285
286 RatePolicy const&
287 policy() const noexcept
288 {
289 return this->boost::empty_value<RatePolicy>::get();
290 }
291
292 template<class Executor2>
293 void on_timer(Executor2 const& ex2);
294
295 void reset(); // set timeouts to never
296 void close() noexcept; // cancel everything
297 };
298
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_;
304
305 template<class Executor2>
306 struct timeout_handler;
307
308 struct ops;
309
310 #if ! BOOST_BEAST_DOXYGEN
311 // boost::asio::ssl::stream needs these
312 // DEPRECATED
313 template<class>
314 friend class boost::asio::ssl::stream;
315 // DEPRECATED
316 using lowest_layer_type = socket_type;
317 // DEPRECATED
318 lowest_layer_type&
319 lowest_layer() noexcept
320 {
321 return impl_->socket;
322 }
323 // DEPRECATED
324 lowest_layer_type const&
325 lowest_layer() const noexcept
326 {
327 return impl_->socket;
328 }
329 #endif
330
331 public:
332 /** Destructor
333
334 This function destroys the stream, cancelling any outstanding
335 asynchronous operations associated with the socket as if by
336 calling cancel.
337 */
338 ~basic_stream();
339
340 /** Constructor
341
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.
345
346 @param args A list of parameters forwarded to the constructor of
347 the underlying socket.
348 */
349 #if BOOST_BEAST_DOXYGEN
350 template<class... Args>
351 explicit
352 basic_stream(Args&&... args);
353 #else
354 template<class Arg0, class... Args,
355 class = typename std::enable_if<
356 ! std::is_constructible<RatePolicy, Arg0>::value>::type>
357 explicit
358 basic_stream(Arg0&& argo, Args&&... args);
359 #endif
360
361 /** Constructor
362
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.
367
368 @param policy The rate policy object to use. The stream will
369 take ownership of this object by decay-copy.
370
371 @param args A list of parameters forwarded to the constructor of
372 the underlying socket.
373 */
374 #if BOOST_BEAST_DOXYGEN
375 template<class RatePolicy_, class... Args>
376 explicit
377 basic_stream(RatePolicy_&& policy, Args&&... args);
378 #else
379 template<class RatePolicy_, class Arg0, class... Args,
380 class = typename std::enable_if<
381 std::is_constructible<
382 RatePolicy, RatePolicy_>::value>::type>
383 basic_stream(
384 RatePolicy_&& policy, Arg0&& arg, Args&&... args);
385 #endif
386
387 /** Move constructor
388
389 @param other The other object from which the move will occur.
390
391 @note Following the move, the moved-from object is in the
392 same state as if newly constructed.
393 */
394 basic_stream(basic_stream&& other);
395
396 /// Move assignment (deleted).
397 basic_stream& operator=(basic_stream&&) = delete;
398
399 /// Return a reference to the underlying socket
400 socket_type&
401 socket() noexcept
402 {
403 return impl_->socket;
404 }
405
406 /// Return a reference to the underlying socket
407 socket_type const&
408 socket() const noexcept
409 {
410 return impl_->socket;
411 }
412
413 /** Release ownership of the underlying socket.
414
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.
419 */
420 socket_type
421 release_socket();
422
423 //--------------------------------------------------------------------------
424
425 /// Returns the rate policy associated with the object
426 RatePolicy&
427 rate_policy() noexcept
428 {
429 return impl_->policy();
430 }
431
432 /// Returns the rate policy associated with the object
433 RatePolicy const&
434 rate_policy() const noexcept
435 {
436 return impl_->policy();
437 }
438
439 /** Set the timeout for the next logical operation.
440
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.
449
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.
454
455 @param expiry_time The amount of time after which a logical
456 operation should be considered timed out.
457 */
458 void
459 expires_after(
460 net::steady_timer::duration expiry_time);
461
462 /** Set the timeout for the next logical operation.
463
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
471 immediately.
472
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.
477
478 @param expiry_time The time point after which a logical
479 operation should be considered timed out.
480 */
481 void
482 expires_at(net::steady_timer::time_point expiry_time);
483
484 /// Disable the timeout for the next logical operation.
485 void
486 expires_never();
487
488 /** Cancel all asynchronous operations associated with the socket.
489
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).
497 */
498 void
499 cancel();
500
501 /** Close the timed stream.
502
503 This cancels all of the outstanding asynchronous operations
504 as if by calling @ref cancel, and closes the underlying socket.
505 */
506 void
507 close();
508
509 //--------------------------------------------------------------------------
510
511 /** Get the executor associated with the object.
512
513 This function may be used to obtain the executor object that the
514 stream uses to dispatch completion handlers without an assocaited
515 executor.
516
517 @return A copy of the executor that stream will use to dispatch handlers.
518 */
519 executor_type
520 get_executor() noexcept
521 {
522 return impl_->ex();
523 }
524
525 /** Connect the stream to the specified endpoint.
526
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.
533
534 @param ep The remote endpoint to connect to.
535
536 @throws system_error Thrown on failure.
537
538 @see connect
539 */
540 void
541 connect(endpoint_type const& ep)
542 {
543 socket().connect(ep);
544 }
545
546 /** Connect the stream to the specified endpoint.
547
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.
554
555 @param ep The remote endpoint to connect to.
556
557 @param ec Set to indicate what error occurred, if any.
558
559 @see connect
560 */
561 void
562 connect(endpoint_type const& ep, error_code& ec)
563 {
564 socket().connect(ep, ec);
565 }
566
567 /** Establishes a connection by trying each endpoint in a sequence.
568
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
571 established.
572 The underlying socket is automatically opened if needed.
573 An automatically opened socket is not returned to the
574 closed state upon failure.
575
576 The algorithm, known as a <em>composed operation</em>, is implemented
577 in terms of calls to the underlying socket's `connect` function.
578
579 @param endpoints A sequence of endpoints.
580
581 @returns The successfully connected endpoint.
582
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.
586 */
587 template<class EndpointSequence
588 #if ! BOOST_BEAST_DOXYGEN
589 ,class = typename std::enable_if<
590 net::is_endpoint_sequence<
591 EndpointSequence>::value>::type
592 #endif
593 >
594 typename Protocol::endpoint
595 connect(EndpointSequence const& endpoints)
596 {
597 return net::connect(socket(), endpoints);
598 }
599
600 /** Establishes a connection by trying each endpoint in a sequence.
601
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
604 established.
605 The underlying socket is automatically opened if needed.
606 An automatically opened socket is not returned to the
607 closed state upon failure.
608
609 The algorithm, known as a <em>composed operation</em>, is implemented
610 in terms of calls to the underlying socket's `connect` function.
611
612 @param endpoints A sequence of endpoints.
613
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.
617
618 @returns On success, the successfully connected endpoint. Otherwise, a
619 default-constructed endpoint.
620 */
621 template<class EndpointSequence
622 #if ! BOOST_BEAST_DOXYGEN
623 ,class = typename std::enable_if<
624 net::is_endpoint_sequence<
625 EndpointSequence>::value>::type
626 #endif
627 >
628 typename Protocol::endpoint
629 connect(
630 EndpointSequence const& endpoints,
631 error_code& ec
632 )
633 {
634 return net::connect(socket(), endpoints, ec);
635 }
636
637 /** Establishes a connection by trying each endpoint in a sequence.
638
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
641 established.
642 The underlying socket is automatically opened if needed.
643 An automatically opened socket is not returned to the
644 closed state upon failure.
645
646 The algorithm, known as a <em>composed operation</em>, is implemented
647 in terms of calls to the underlying socket's `connect` function.
648
649 @param begin An iterator pointing to the start of a sequence of endpoints.
650
651 @param end An iterator pointing to the end of a sequence of endpoints.
652
653 @returns An iterator denoting the successfully connected endpoint.
654
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.
658 */
659 template<class Iterator>
660 Iterator
661 connect(
662 Iterator begin, Iterator end)
663 {
664 return net::connect(socket(), begin, end);
665 }
666
667 /** Establishes a connection by trying each endpoint in a sequence.
668
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
671 established.
672 The underlying socket is automatically opened if needed.
673 An automatically opened socket is not returned to the
674 closed state upon failure.
675
676 The algorithm, known as a <em>composed operation</em>, is implemented
677 in terms of calls to the underlying socket's `connect` function.
678
679 @param begin An iterator pointing to the start of a sequence of endpoints.
680
681 @param end An iterator pointing to the end of a sequence of endpoints.
682
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.
686
687 @returns On success, an iterator denoting the successfully connected
688 endpoint. Otherwise, the end iterator.
689 */
690 template<class Iterator>
691 Iterator
692 connect(
693 Iterator begin, Iterator end,
694 error_code& ec)
695 {
696 return net::connect(socket(), begin, end, ec);
697 }
698
699 /** Establishes a connection by trying each endpoint in a sequence.
700
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
703 established.
704 The underlying socket is automatically opened if needed.
705 An automatically opened socket is not returned to the
706 closed state upon failure.
707
708 The algorithm, known as a <em>composed operation</em>, is implemented
709 in terms of calls to the underlying socket's `connect` function.
710
711 @param endpoints A sequence of endpoints.
712
713 @param connect_condition A function object that is called prior to each
714 connection attempt. The signature of the function object must be:
715 @code
716 bool connect_condition(
717 error_code const& ec,
718 typename Protocol::endpoint const& next);
719 @endcode
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.
725
726 @returns The successfully connected endpoint.
727
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.
731 */
732 template<
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
738 #endif
739 >
740 typename Protocol::endpoint
741 connect(
742 EndpointSequence const& endpoints,
743 ConnectCondition connect_condition
744 )
745 {
746 return net::connect(socket(), endpoints, connect_condition);
747 }
748
749 /** Establishes a connection by trying each endpoint in a sequence.
750
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
753 established.
754 The underlying socket is automatically opened if needed.
755 An automatically opened socket is not returned to the
756 closed state upon failure.
757
758 The algorithm, known as a <em>composed operation</em>, is implemented
759 in terms of calls to the underlying socket's `connect` function.
760
761 @param endpoints A sequence of endpoints.
762
763 @param connect_condition A function object that is called prior to each
764 connection attempt. The signature of the function object must be:
765 @code
766 bool connect_condition(
767 error_code const& ec,
768 typename Protocol::endpoint const& next);
769 @endcode
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.
775
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.
779
780 @returns On success, the successfully connected endpoint. Otherwise, a
781 default-constructed endpoint.
782 */
783 template<
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
789 #endif
790 >
791 typename Protocol::endpoint
792 connect(
793 EndpointSequence const& endpoints,
794 ConnectCondition connect_condition,
795 error_code& ec)
796 {
797 return net::connect(socket(), endpoints, connect_condition, ec);
798 }
799
800 /** Establishes a connection by trying each endpoint in a sequence.
801
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
804 established.
805 The underlying socket is automatically opened if needed.
806 An automatically opened socket is not returned to the
807 closed state upon failure.
808
809 The algorithm, known as a <em>composed operation</em>, is implemented
810 in terms of calls to the underlying socket's `connect` function.
811
812 @param begin An iterator pointing to the start of a sequence of endpoints.
813
814 @param end An iterator pointing to the end of a sequence of endpoints.
815
816 @param connect_condition A function object that is called prior to each
817 connection attempt. The signature of the function object must be:
818 @code
819 bool connect_condition(
820 error_code const& ec,
821 typename Protocol::endpoint const& next);
822 @endcode
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.
828
829 @returns An iterator denoting the successfully connected endpoint.
830
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.
834 */
835 template<
836 class Iterator, class ConnectCondition>
837 Iterator
838 connect(
839 Iterator begin, Iterator end,
840 ConnectCondition connect_condition)
841 {
842 return net::connect(socket(), begin, end, connect_condition);
843 }
844
845 /** Establishes a connection by trying each endpoint in a sequence.
846
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
849 established.
850 The underlying socket is automatically opened if needed.
851 An automatically opened socket is not returned to the
852 closed state upon failure.
853
854 The algorithm, known as a <em>composed operation</em>, is implemented
855 in terms of calls to the underlying socket's `connect` function.
856
857 @param begin An iterator pointing to the start of a sequence of endpoints.
858
859 @param end An iterator pointing to the end of a sequence of endpoints.
860
861 @param connect_condition A function object that is called prior to each
862 connection attempt. The signature of the function object must be:
863 @code
864 bool connect_condition(
865 error_code const& ec,
866 typename Protocol::endpoint const& next);
867 @endcode
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.
873
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.
877
878 @returns On success, an iterator denoting the successfully connected
879 endpoint. Otherwise, the end iterator.
880 */
881 template<
882 class Iterator, class ConnectCondition>
883 Iterator
884 connect(
885 Iterator begin, Iterator end,
886 ConnectCondition connect_condition,
887 error_code& ec)
888 {
889 return net::connect(socket(), begin, end, connect_condition, ec);
890 }
891
892 /** Connect the stream to the specified endpoint asynchronously.
893
894 This function is used to asynchronously connect the underlying
895 socket to the specified remote endpoint. The function call always
896 returns immediately.
897 The underlying socket is automatically opened if needed.
898 An automatically opened socket is not returned to the
899 closed state upon failure.
900
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.
904
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.
907
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
911 the handler must be:
912 @code
913 void handler(
914 error_code ec // Result of operation
915 );
916 @endcode
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`.
921
922 @see async_connect
923 */
924 template<
925 BOOST_BEAST_ASYNC_TPARAM1 ConnectHandler =
926 net::default_completion_token_t<executor_type>
927 >
928 BOOST_BEAST_ASYNC_RESULT1(ConnectHandler)
929 async_connect(
930 endpoint_type const& ep,
931 ConnectHandler&& handler =
932 net::default_completion_token_t<
933 executor_type>{});
934
935 /** Establishes a connection by trying each endpoint in a sequence asynchronously.
936
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
939 established.
940 The underlying socket is automatically opened if needed.
941 An automatically opened socket is not returned to the
942 closed state upon failure.
943
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`
946 function.
947
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.
951
952 @param endpoints A sequence of endpoints. This this object must meet
953 the requirements of <em>EndpointSequence</em>.
954
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
958 the handler must be:
959 @code
960 void handler(
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,
965
966 // On success, the successfully connected endpoint.
967 // Otherwise, a default-constructed endpoint.
968 typename Protocol::endpoint const& endpoint
969 );
970 @endcode
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`.
975 */
976 template<
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
986 #endif
987 >
988 BOOST_ASIO_INITFN_RESULT_TYPE(
989 RangeConnectHandler,
990 void(error_code, typename Protocol::endpoint))
991 async_connect(
992 EndpointSequence const& endpoints,
993 RangeConnectHandler&& handler =
994 net::default_completion_token_t<executor_type>{});
995
996 /** Establishes a connection by trying each endpoint in a sequence asynchronously.
997
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
1000 established.
1001 The underlying socket is automatically opened if needed.
1002 An automatically opened socket is not returned to the
1003 closed state upon failure.
1004
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`
1007 function.
1008
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.
1012
1013 @param endpoints A sequence of endpoints. This this object must meet
1014 the requirements of <em>EndpointSequence</em>.
1015
1016 @param connect_condition A function object that is called prior to each
1017 connection attempt. The signature of the function object must be:
1018 @code
1019 bool connect_condition(
1020 error_code const& ec,
1021 typename Protocol::endpoint const& next);
1022 @endcode
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.
1028
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:
1033 @code
1034 void handler(
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,
1039
1040 // On success, the successfully connected endpoint.
1041 // Otherwise, a default-constructed endpoint.
1042 typename Protocol::endpoint const& endpoint
1043 );
1044 @endcode
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`.
1049
1050 @par Example
1051 The following connect condition function object can be used to output
1052 information about the individual connection attempts:
1053 @code
1054 struct my_connect_condition
1055 {
1056 bool operator()(
1057 error_code const& ec,
1058 net::ip::tcp::endpoint const& next)
1059 {
1060 if (ec)
1061 std::cout << "Error: " << ec.message() << std::endl;
1062 std::cout << "Trying: " << next << std::endl;
1063 return true;
1064 }
1065 };
1066 @endcode
1067 */
1068 template<
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
1079 #endif
1080 >
1081 BOOST_ASIO_INITFN_RESULT_TYPE(
1082 RangeConnectHandler,
1083 void(error_code, typename Protocol::endpoint))
1084 async_connect(
1085 EndpointSequence const& endpoints,
1086 ConnectCondition connect_condition,
1087 RangeConnectHandler&& handler =
1088 net::default_completion_token_t<
1089 executor_type>{});
1090
1091 /** Establishes a connection by trying each endpoint in a sequence asynchronously.
1092
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
1095 established.
1096 The underlying socket is automatically opened if needed.
1097 An automatically opened socket is not returned to the
1098 closed state upon failure.
1099
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`
1102 function.
1103
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.
1107
1108 @param begin An iterator pointing to the start of a sequence of endpoints.
1109
1110 @param end An iterator pointing to the end of a sequence of endpoints.
1111
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:
1116 @code
1117 void handler(
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,
1122
1123 // On success, an iterator denoting the successfully
1124 // connected endpoint. Otherwise, the end iterator.
1125 Iterator iterator
1126 );
1127 @endcode
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`.
1132 */
1133 template<
1134 class Iterator,
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))
1142 async_connect(
1143 Iterator begin, Iterator end,
1144 IteratorConnectHandler&& handler =
1145 net::default_completion_token_t<executor_type>{});
1146
1147 /** Establishes a connection by trying each endpoint in a sequence asynchronously.
1148
1149 This function attempts to connect the stream to one of a sequence of
1150 endpoints by trying each endpoint until a connection is successfully
1151 established.
1152 The algorithm, known as a <em>composed asynchronous operation</em>, is
1153 implemented in terms of calls to the underlying socket's `async_connect`
1154 function.
1155
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.
1159
1160 @param begin An iterator pointing to the start of a sequence of endpoints.
1161
1162 @param end An iterator pointing to the end of a sequence of endpoints.
1163
1164 @param connect_condition A function object that is called prior to each
1165 connection attempt. The signature of the function object must be:
1166 @code
1167 bool connect_condition(
1168 error_code const& ec,
1169 typename Protocol::endpoint const& next);
1170 @endcode
1171
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:
1176 @code
1177 void handler(
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,
1182
1183 // On success, an iterator denoting the successfully
1184 // connected endpoint. Otherwise, the end iterator.
1185 Iterator iterator
1186 );
1187 @endcode
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`.
1192 */
1193 template<
1194 class Iterator,
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))
1203 async_connect(
1204 Iterator begin, Iterator end,
1205 ConnectCondition connect_condition,
1206 IteratorConnectHandler&& handler =
1207 net::default_completion_token_t<executor_type>{});
1208
1209 //--------------------------------------------------------------------------
1210
1211 /** Read some data.
1212
1213 This function is used to read some data from the stream.
1214
1215 The call blocks until one of the following is true:
1216
1217 @li One or more bytes are read from the stream.
1218
1219 @li An error occurs.
1220
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.
1224
1225 @returns The number of bytes read.
1226
1227 @throws system_error Thrown on failure.
1228
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.
1233 */
1234 template<class MutableBufferSequence>
1235 std::size_t
1236 read_some(MutableBufferSequence const& buffers)
1237 {
1238 return impl_->socket.read_some(buffers);
1239 }
1240
1241 /** Read some data.
1242
1243 This function is used to read some data from the underlying socket.
1244
1245 The call blocks until one of the following is true:
1246
1247 @li One or more bytes are read from the stream.
1248
1249 @li An error occurs.
1250
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.
1254
1255 @param ec Set to indicate what error occurred, if any.
1256
1257 @returns The number of bytes read.
1258
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.
1263 */
1264 template<class MutableBufferSequence>
1265 std::size_t
1266 read_some(
1267 MutableBufferSequence const& buffers,
1268 error_code& ec)
1269 {
1270 return impl_->socket.read_some(buffers, ec);
1271 }
1272
1273 /** Read some data asynchronously.
1274
1275 This function is used to asynchronously read data from the stream.
1276
1277 This call always returns immediately. The asynchronous operation
1278 will continue until one of the following conditions is true:
1279
1280 @li One or more bytes are read from the stream.
1281
1282 @li An error occurs.
1283
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.
1288
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.
1292
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
1295 with no error.
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.
1299
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:
1304 @code
1305 void handler(
1306 error_code error, // Result of operation.
1307 std::size_t bytes_transferred // Number of bytes read.
1308 );
1309 @endcode
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`.
1314
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.
1319 */
1320 template<
1321 class MutableBufferSequence,
1322 BOOST_BEAST_ASYNC_TPARAM2 ReadHandler =
1323 net::default_completion_token_t<executor_type>
1324 >
1325 BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
1326 async_read_some(
1327 MutableBufferSequence const& buffers,
1328 ReadHandler&& handler =
1329 net::default_completion_token_t<executor_type>{}
1330 );
1331
1332 /** Write some data.
1333
1334 This function is used to write some data to the stream.
1335
1336 The call blocks until one of the following is true:
1337
1338 @li One or more bytes are written to the stream.
1339
1340 @li An error occurs.
1341
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
1344 with no error.
1345
1346 @returns The number of bytes written.
1347
1348 @throws system_error Thrown on failure.
1349
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.
1354 */
1355 template<class ConstBufferSequence>
1356 std::size_t
1357 write_some(ConstBufferSequence const& buffers)
1358 {
1359 return impl_->socket.write_some(buffers);
1360 }
1361
1362 /** Write some data.
1363
1364 This function is used to write some data to the stream.
1365
1366 The call blocks until one of the following is true:
1367
1368 @li One or more bytes are written to the stream.
1369
1370 @li An error occurs.
1371
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
1374 with no error.
1375
1376 @param ec Set to indicate what error occurred, if any.
1377
1378 @returns The number of bytes written.
1379
1380 @throws system_error Thrown on failure.
1381
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.
1386 */
1387 template<class ConstBufferSequence>
1388 std::size_t
1389 write_some(
1390 ConstBufferSequence const& buffers,
1391 error_code& ec)
1392 {
1393 return impl_->socket.write_some(buffers, ec);
1394 }
1395
1396 /** Write some data asynchronously.
1397
1398 This function is used to asynchronously write data to the underlying socket.
1399
1400 This call always returns immediately. The asynchronous operation
1401 will continue until one of the following conditions is true:
1402
1403 @li One or more bytes are written to the stream.
1404
1405 @li An error occurs.
1406
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.
1411
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.
1415
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.
1422
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:
1427 @code
1428 void handler(
1429 error_code error, // Result of operation.
1430 std::size_t bytes_transferred // Number of bytes written.
1431 );
1432 @endcode
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`.
1437
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.
1442 */
1443 template<
1444 class ConstBufferSequence,
1445 BOOST_BEAST_ASYNC_TPARAM2 WriteHandler =
1446 net::default_completion_token_t<Executor>
1447 >
1448 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
1449 async_write_some(
1450 ConstBufferSequence const& buffers,
1451 WriteHandler&& handler =
1452 net::default_completion_token_t<Executor>{});
1453 };
1454
1455 } // beast
1456 } // boost
1457
1458 #include <boost/beast/core/impl/basic_stream.hpp>
1459
1460 #endif