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
33namespace boost {
34namespace asio {
35namespace ssl {
36template<typename> class stream;
37} // ssl
38} // asio
39} // boost
40#endif
41
42namespace boost {
43namespace 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*/
198template<
199 class Protocol,
200 class Executor = net::any_io_executor,
201 class RatePolicy = unlimited_rate_policy
202>
203class basic_stream
204#if ! BOOST_BEAST_DOXYGEN
205 : private detail::stream_base
206#endif
207{
208public:
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
235private:
236 using op_state = basic_op_state<Executor>;
237 static_assert(
238 net::is_executor<Executor>::value || net::execution::is_executor<Executor>::value,
239 "Executor type requirements not met");
240
241 struct impl_type
242 : boost::enable_shared_from_this<impl_type>
243 , boost::empty_value<RatePolicy>
244 {
245 // must come first
246 net::basic_stream_socket<
247 Protocol, Executor> socket;
248
249 op_state read;
250 op_state write;
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
257 int waiting = 0;
258
259 impl_type(impl_type&&) = default;
260
261 template<class... Args>
262 explicit
263 impl_type(std::false_type, Args&&...);
264
265 template<class RatePolicy_, class... Args>
266 explicit
267 impl_type(std::true_type,
268 RatePolicy_&& policy, Args&&...);
269
270 impl_type& operator=(impl_type&&) = delete;
271
272 beast::executor_type<socket_type>
273 ex() noexcept
274 {
275 return this->socket.get_executor();
276 }
277
278 RatePolicy&
279 policy() noexcept
280 {
281 return this->boost::empty_value<RatePolicy>::get();
282 }
283
284 RatePolicy const&
285 policy() const noexcept
286 {
287 return this->boost::empty_value<RatePolicy>::get();
288 }
289
290 template<class Executor2>
291 void on_timer(Executor2 const& ex2);
292
293 void reset(); // set timeouts to never
294 void close() noexcept; // cancel everything
295 };
296
297 // We use shared ownership for the state so it can
298 // outlive the destruction of the stream_socket object,
299 // in the case where there is no outstanding read or write
300 // but the implementation is still waiting on a timer.
301 boost::shared_ptr<impl_type> impl_;
302
303 template<class Executor2>
304 struct timeout_handler;
305
306 struct ops;
307
308#if ! BOOST_BEAST_DOXYGEN
309 // boost::asio::ssl::stream needs these
310 // DEPRECATED
311 template<class>
312 friend class boost::asio::ssl::stream;
313 // DEPRECATED
314 using lowest_layer_type = socket_type;
315 // DEPRECATED
316 lowest_layer_type&
317 lowest_layer() noexcept
318 {
319 return impl_->socket;
320 }
321 // DEPRECATED
322 lowest_layer_type const&
323 lowest_layer() const noexcept
324 {
325 return impl_->socket;
326 }
327#endif
328
329public:
330 /** Destructor
331
332 This function destroys the stream, cancelling any outstanding
333 asynchronous operations associated with the socket as if by
334 calling cancel.
335 */
336 ~basic_stream();
337
338 /** Constructor
339
340 This constructor creates the stream by forwarding all arguments
341 to the underlying socket. The socket then needs to be open and
342 connected or accepted before data can be sent or received on it.
343
344 @param args A list of parameters forwarded to the constructor of
345 the underlying socket.
346 */
347#if BOOST_BEAST_DOXYGEN
348 template<class... Args>
349 explicit
350 basic_stream(Args&&... args);
351#else
352 template<class Arg0, class... Args,
353 class = typename std::enable_if<
354 ! std::is_constructible<RatePolicy, Arg0>::value>::type>
355 explicit
356 basic_stream(Arg0&& argo, Args&&... args);
357
358
359 /** Constructor
360 *
361 * A constructor that rebinds the executor.
362 *
363 * @tparam Executor_ The new executor
364 * @param other The original socket to be rebound.
365 */
366 template<class Executor_>
367 explicit
368 basic_stream(basic_stream<Protocol, Executor_, RatePolicy> && other);
369
370
371 template<typename, typename, typename>
372 friend class basic_stream;
373#endif
374
375 /** Constructor
376
377 This constructor creates the stream with the specified rate
378 policy, and forwards all remaining arguments to the underlying
379 socket. The socket then needs to be open and connected or
380 accepted before data can be sent or received on it.
381
382 @param policy The rate policy object to use. The stream will
383 take ownership of this object by decay-copy.
384
385 @param args A list of parameters forwarded to the constructor of
386 the underlying socket.
387 */
388#if BOOST_BEAST_DOXYGEN
389 template<class RatePolicy_, class... Args>
390 explicit
391 basic_stream(RatePolicy_&& policy, Args&&... args);
392#else
393 template<class RatePolicy_, class Arg0, class... Args,
394 class = typename std::enable_if<
395 std::is_constructible<
396 RatePolicy, RatePolicy_>::value>::type>
397 basic_stream(
398 RatePolicy_&& policy, Arg0&& arg, Args&&... args);
399#endif
400
401 /** Move constructor
402
403 @param other The other object from which the move will occur.
404
405 @note Following the move, the moved-from object is in the
406 same state as if newly constructed.
407 */
408 basic_stream(basic_stream&& other);
409
410 /// Move assignment (deleted).
411 basic_stream& operator=(basic_stream&&) = delete;
412
413 /// Return a reference to the underlying socket
414 socket_type&
415 socket() noexcept
416 {
417 return impl_->socket;
418 }
419
420 /// Return a reference to the underlying socket
421 socket_type const&
422 socket() const noexcept
423 {
424 return impl_->socket;
425 }
426
427 /** Release ownership of the underlying socket.
428
429 This function causes all outstanding asynchronous connect,
430 read, and write operations to be canceled as if by a call
431 to @ref cancel. Ownership of the underlying socket is then
432 transferred to the caller.
433 */
434 socket_type
435 release_socket();
436
437 //--------------------------------------------------------------------------
438
439 /// Returns the rate policy associated with the object
440 RatePolicy&
441 rate_policy() noexcept
442 {
443 return impl_->policy();
444 }
445
446 /// Returns the rate policy associated with the object
447 RatePolicy const&
448 rate_policy() const noexcept
449 {
450 return impl_->policy();
451 }
452
453 /** Set the timeout for subsequent logical operations.
454
455 This sets either the read timer, the write timer, or
456 both timers to expire after the specified amount of time
457 has elapsed. If a timer expires when the corresponding
458 asynchronous operation is outstanding, the stream will be
459 closed and any outstanding operations will complete with the
460 error @ref beast::error::timeout. Otherwise, if the timer
461 expires while no operations are outstanding, and the expiraton
462 is not set again, the next operation will time out immediately.
463
464 The timer applies collectively to any asynchronous reads
465 or writes initiated after the expiration is set, until the
466 expiration is set again. A call to @ref async_connect
467 counts as both a read and a write.
468
469 @param expiry_time The amount of time after which a logical
470 operation should be considered timed out.
471 */
472 void
473 expires_after(
474 net::steady_timer::duration expiry_time);
475
476 /** Set the timeout for subsequent logical operations.
477
478 This sets either the read timer, the write timer, or both
479 timers to expire at the specified time point. If a timer
480 expires when the corresponding asynchronous operation is
481 outstanding, the stream will be closed and any outstanding
482 operations will complete with the error @ref beast::error::timeout.
483 Otherwise, if the timer expires while no operations are outstanding,
484 and the expiraton is not set again, the next operation will time out
485 immediately.
486
487 The timer applies collectively to any asynchronous reads
488 or writes initiated after the expiration is set, until the
489 expiration is set again. A call to @ref async_connect
490 counts as both a read and a write.
491
492 @param expiry_time The time point after which a logical
493 operation should be considered timed out.
494 */
495 void
496 expires_at(net::steady_timer::time_point expiry_time);
497
498 /// Disable the timeout for subsequent logical operations.
499 void
500 expires_never();
501
502 /** Cancel all asynchronous operations associated with the socket.
503
504 This function causes all outstanding asynchronous connect,
505 read, and write operations to finish immediately. Completion
506 handlers for cancelled operations will receive the error
507 `net::error::operation_aborted`. Completion handlers not
508 yet invoked whose operations have completed, will receive
509 the error corresponding to the result of the operation (which
510 may indicate success).
511 */
512 void
513 cancel();
514
515 /** Close the timed stream.
516
517 This cancels all of the outstanding asynchronous operations
518 as if by calling @ref cancel, and closes the underlying socket.
519 */
520 void
521 close();
522
523 //--------------------------------------------------------------------------
524
525 /** Get the executor associated with the object.
526
527 This function may be used to obtain the executor object that the
528 stream uses to dispatch completion handlers without an assocaited
529 executor.
530
531 @return A copy of the executor that stream will use to dispatch handlers.
532 */
533 executor_type
534 get_executor() noexcept
535 {
536 return impl_->ex();
537 }
538
539 /** Connect the stream to the specified endpoint.
540
541 This function is used to connect the underlying socket to the
542 specified remote endpoint. The function call will block until
543 the connection is successfully made or an error occurs.
544 The underlying socket is automatically opened if needed.
545 An automatically opened socket is not returned to the
546 closed state upon failure.
547
548 @param ep The remote endpoint to connect to.
549
550 @throws system_error Thrown on failure.
551
552 @see connect
553 */
554 void
555 connect(endpoint_type const& ep)
556 {
557 socket().connect(ep);
558 }
559
560 /** Connect the stream to the specified endpoint.
561
562 This function is used to connect the underlying socket to the
563 specified remote endpoint. The function call will block until
564 the connection is successfully made or an error occurs.
565 The underlying socket is automatically opened if needed.
566 An automatically opened socket is not returned to the
567 closed state upon failure.
568
569 @param ep The remote endpoint to connect to.
570
571 @param ec Set to indicate what error occurred, if any.
572
573 @see connect
574 */
575 void
576 connect(endpoint_type const& ep, error_code& ec)
577 {
578 socket().connect(ep, ec);
579 }
580
581 /** Establishes a connection by trying each endpoint in a sequence.
582
583 This function attempts to connect the stream to one of a sequence of
584 endpoints by trying each endpoint until a connection is successfully
585 established.
586 The underlying socket is automatically opened if needed.
587 An automatically opened socket is not returned to the
588 closed state upon failure.
589
590 The algorithm, known as a <em>composed operation</em>, is implemented
591 in terms of calls to the underlying socket's `connect` function.
592
593 @param endpoints A sequence of endpoints.
594
595 @returns The successfully connected endpoint.
596
597 @throws system_error Thrown on failure. If the sequence is
598 empty, the associated error code is `net::error::not_found`.
599 Otherwise, contains the error from the last connection attempt.
600 */
601 template<class EndpointSequence
602 #if ! BOOST_BEAST_DOXYGEN
603 ,class = typename std::enable_if<
604 net::is_endpoint_sequence<
605 EndpointSequence>::value>::type
606 #endif
607 >
608 typename Protocol::endpoint
609 connect(EndpointSequence const& endpoints)
610 {
611 return net::connect(socket(), endpoints);
612 }
613
614 /** Establishes a connection by trying each endpoint in a sequence.
615
616 This function attempts to connect the stream to one of a sequence of
617 endpoints by trying each endpoint until a connection is successfully
618 established.
619 The underlying socket is automatically opened if needed.
620 An automatically opened socket is not returned to the
621 closed state upon failure.
622
623 The algorithm, known as a <em>composed operation</em>, is implemented
624 in terms of calls to the underlying socket's `connect` function.
625
626 @param endpoints A sequence of endpoints.
627
628 @param ec Set to indicate what error occurred, if any. If the sequence is
629 empty, set to `net::error::not_found`. Otherwise, contains the error
630 from the last connection attempt.
631
632 @returns On success, the successfully connected endpoint. Otherwise, a
633 default-constructed endpoint.
634 */
635 template<class EndpointSequence
636 #if ! BOOST_BEAST_DOXYGEN
637 ,class = typename std::enable_if<
638 net::is_endpoint_sequence<
639 EndpointSequence>::value>::type
640 #endif
641 >
642 typename Protocol::endpoint
643 connect(
644 EndpointSequence const& endpoints,
645 error_code& ec
646 )
647 {
648 return net::connect(socket(), endpoints, ec);
649 }
650
651 /** Establishes a connection by trying each endpoint in a sequence.
652
653 This function attempts to connect the stream to one of a sequence of
654 endpoints by trying each endpoint until a connection is successfully
655 established.
656 The underlying socket is automatically opened if needed.
657 An automatically opened socket is not returned to the
658 closed state upon failure.
659
660 The algorithm, known as a <em>composed operation</em>, is implemented
661 in terms of calls to the underlying socket's `connect` function.
662
663 @param begin An iterator pointing to the start of a sequence of endpoints.
664
665 @param end An iterator pointing to the end of a sequence of endpoints.
666
667 @returns An iterator denoting the successfully connected endpoint.
668
669 @throws system_error Thrown on failure. If the sequence is
670 empty, the associated error code is `net::error::not_found`.
671 Otherwise, contains the error from the last connection attempt.
672 */
673 template<class Iterator>
674 Iterator
675 connect(
676 Iterator begin, Iterator end)
677 {
678 return net::connect(socket(), begin, end);
679 }
680
681 /** Establishes a connection by trying each endpoint in a sequence.
682
683 This function attempts to connect the stream to one of a sequence of
684 endpoints by trying each endpoint until a connection is successfully
685 established.
686 The underlying socket is automatically opened if needed.
687 An automatically opened socket is not returned to the
688 closed state upon failure.
689
690 The algorithm, known as a <em>composed operation</em>, is implemented
691 in terms of calls to the underlying socket's `connect` function.
692
693 @param begin An iterator pointing to the start of a sequence of endpoints.
694
695 @param end An iterator pointing to the end of a sequence of endpoints.
696
697 @param ec Set to indicate what error occurred, if any. If the sequence is
698 empty, set to boost::asio::error::not_found. Otherwise, contains the error
699 from the last connection attempt.
700
701 @returns On success, an iterator denoting the successfully connected
702 endpoint. Otherwise, the end iterator.
703 */
704 template<class Iterator>
705 Iterator
706 connect(
707 Iterator begin, Iterator end,
708 error_code& ec)
709 {
710 return net::connect(socket(), begin, end, ec);
711 }
712
713 /** Establishes a connection by trying each endpoint in a sequence.
714
715 This function attempts to connect the stream to one of a sequence of
716 endpoints by trying each endpoint until a connection is successfully
717 established.
718 The underlying socket is automatically opened if needed.
719 An automatically opened socket is not returned to the
720 closed state upon failure.
721
722 The algorithm, known as a <em>composed operation</em>, is implemented
723 in terms of calls to the underlying socket's `connect` function.
724
725 @param endpoints A sequence of endpoints.
726
727 @param connect_condition A function object that is called prior to each
728 connection attempt. The signature of the function object must be:
729 @code
730 bool connect_condition(
731 error_code const& ec,
732 typename Protocol::endpoint const& next);
733 @endcode
734 The @c ec parameter contains the result from the most recent connect
735 operation. Before the first connection attempt, @c ec is always set to
736 indicate success. The @c next parameter is the next endpoint to be tried.
737 The function object should return true if the next endpoint should be tried,
738 and false if it should be skipped.
739
740 @returns The successfully connected endpoint.
741
742 @throws boost::system::system_error Thrown on failure. If the sequence is
743 empty, the associated error code is `net::error::not_found`.
744 Otherwise, contains the error from the last connection attempt.
745 */
746 template<
747 class EndpointSequence, class ConnectCondition
748 #if ! BOOST_BEAST_DOXYGEN
749 ,class = typename std::enable_if<
750 net::is_endpoint_sequence<
751 EndpointSequence>::value>::type
752 #endif
753 >
754 typename Protocol::endpoint
755 connect(
756 EndpointSequence const& endpoints,
757 ConnectCondition connect_condition
758 )
759 {
760 return net::connect(socket(), endpoints, connect_condition);
761 }
762
763 /** Establishes a connection by trying each endpoint in a sequence.
764
765 This function attempts to connect the stream to one of a sequence of
766 endpoints by trying each endpoint until a connection is successfully
767 established.
768 The underlying socket is automatically opened if needed.
769 An automatically opened socket is not returned to the
770 closed state upon failure.
771
772 The algorithm, known as a <em>composed operation</em>, is implemented
773 in terms of calls to the underlying socket's `connect` function.
774
775 @param endpoints A sequence of endpoints.
776
777 @param connect_condition A function object that is called prior to each
778 connection attempt. The signature of the function object must be:
779 @code
780 bool connect_condition(
781 error_code const& ec,
782 typename Protocol::endpoint const& next);
783 @endcode
784 The @c ec parameter contains the result from the most recent connect
785 operation. Before the first connection attempt, @c ec is always set to
786 indicate success. The @c next parameter is the next endpoint to be tried.
787 The function object should return true if the next endpoint should be tried,
788 and false if it should be skipped.
789
790 @param ec Set to indicate what error occurred, if any. If the sequence is
791 empty, set to `net::error::not_found`. Otherwise, contains the error
792 from the last connection attempt.
793
794 @returns On success, the successfully connected endpoint. Otherwise, a
795 default-constructed endpoint.
796 */
797 template<
798 class EndpointSequence, class ConnectCondition
799 #if ! BOOST_BEAST_DOXYGEN
800 ,class = typename std::enable_if<
801 net::is_endpoint_sequence<
802 EndpointSequence>::value>::type
803 #endif
804 >
805 typename Protocol::endpoint
806 connect(
807 EndpointSequence const& endpoints,
808 ConnectCondition connect_condition,
809 error_code& ec)
810 {
811 return net::connect(socket(), endpoints, connect_condition, ec);
812 }
813
814 /** Establishes a connection by trying each endpoint in a sequence.
815
816 This function attempts to connect the stream to one of a sequence of
817 endpoints by trying each endpoint until a connection is successfully
818 established.
819 The underlying socket is automatically opened if needed.
820 An automatically opened socket is not returned to the
821 closed state upon failure.
822
823 The algorithm, known as a <em>composed operation</em>, is implemented
824 in terms of calls to the underlying socket's `connect` function.
825
826 @param begin An iterator pointing to the start of a sequence of endpoints.
827
828 @param end An iterator pointing to the end of a sequence of endpoints.
829
830 @param connect_condition A function object that is called prior to each
831 connection attempt. The signature of the function object must be:
832 @code
833 bool connect_condition(
834 error_code const& ec,
835 typename Protocol::endpoint const& next);
836 @endcode
837 The @c ec parameter contains the result from the most recent connect
838 operation. Before the first connection attempt, @c ec is always set to
839 indicate success. The @c next parameter is the next endpoint to be tried.
840 The function object should return true if the next endpoint should be tried,
841 and false if it should be skipped.
842
843 @returns An iterator denoting the successfully connected endpoint.
844
845 @throws boost::system::system_error Thrown on failure. If the sequence is
846 empty, the associated @c error_code is `net::error::not_found`.
847 Otherwise, contains the error from the last connection attempt.
848 */
849 template<
850 class Iterator, class ConnectCondition>
851 Iterator
852 connect(
853 Iterator begin, Iterator end,
854 ConnectCondition connect_condition)
855 {
856 return net::connect(socket(), begin, end, connect_condition);
857 }
858
859 /** Establishes a connection by trying each endpoint in a sequence.
860
861 This function attempts to connect the stream to one of a sequence of
862 endpoints by trying each endpoint until a connection is successfully
863 established.
864 The underlying socket is automatically opened if needed.
865 An automatically opened socket is not returned to the
866 closed state upon failure.
867
868 The algorithm, known as a <em>composed operation</em>, is implemented
869 in terms of calls to the underlying socket's `connect` function.
870
871 @param begin An iterator pointing to the start of a sequence of endpoints.
872
873 @param end An iterator pointing to the end of a sequence of endpoints.
874
875 @param connect_condition A function object that is called prior to each
876 connection attempt. The signature of the function object must be:
877 @code
878 bool connect_condition(
879 error_code const& ec,
880 typename Protocol::endpoint const& next);
881 @endcode
882 The @c ec parameter contains the result from the most recent connect
883 operation. Before the first connection attempt, @c ec is always set to
884 indicate success. The @c next parameter is the next endpoint to be tried.
885 The function object should return true if the next endpoint should be tried,
886 and false if it should be skipped.
887
888 @param ec Set to indicate what error occurred, if any. If the sequence is
889 empty, set to `net::error::not_found`. Otherwise, contains the error
890 from the last connection attempt.
891
892 @returns On success, an iterator denoting the successfully connected
893 endpoint. Otherwise, the end iterator.
894 */
895 template<
896 class Iterator, class ConnectCondition>
897 Iterator
898 connect(
899 Iterator begin, Iterator end,
900 ConnectCondition connect_condition,
901 error_code& ec)
902 {
903 return net::connect(socket(), begin, end, connect_condition, ec);
904 }
905
906 /** Connect the stream to the specified endpoint asynchronously.
907
908 This function is used to asynchronously connect the underlying
909 socket to the specified remote endpoint. The function call always
910 returns immediately.
911 The underlying socket is automatically opened if needed.
912 An automatically opened socket is not returned to the
913 closed state upon failure.
914
915 If the timeout timer expires while the operation is outstanding,
916 the operation will be canceled and the completion handler will be
917 invoked with the error @ref error::timeout.
918
919 @param ep The remote endpoint to which the underlying socket will be
920 connected. Copies will be made of the endpoint object as required.
921
922 @param handler The completion handler to invoke when the operation
923 completes. The implementation takes ownership of the handler by
924 performing a decay-copy. The equivalent function signature of
925 the handler must be:
926 @code
927 void handler(
928 error_code ec // Result of operation
929 );
930 @endcode
931 If the handler has an associated immediate executor,
932 an immediate completion will be dispatched to it.
933 Otherwise, the handler will not be invoked from within
934 this function. Invocation of the handler will be performed
935 by dispatching to the immediate executor. If no
936 immediate executor is specified, this is equivalent
937 to using `net::post`.
938
939 @par Per-Operation Cancellation
940
941 This asynchronous operation supports cancellation for the following
942 net::cancellation_type values:
943
944 @li @c net::cancellation_type::terminal
945 @li @c net::cancellation_type::partial
946 @li @c net::cancellation_type::total
947
948 if they are also supported by the socket's @c async_connect operation.
949
950 @see async_connect
951 */
952 template<
953 BOOST_BEAST_ASYNC_TPARAM1 ConnectHandler =
954 net::default_completion_token_t<executor_type>
955 >
956 BOOST_BEAST_ASYNC_RESULT1(ConnectHandler)
957 async_connect(
958 endpoint_type const& ep,
959 ConnectHandler&& handler =
960 net::default_completion_token_t<
961 executor_type>{});
962
963 /** Establishes a connection by trying each endpoint in a sequence asynchronously.
964
965 This function attempts to connect the stream to one of a sequence of
966 endpoints by trying each endpoint until a connection is successfully
967 established.
968 The underlying socket is automatically opened if needed.
969 An automatically opened socket is not returned to the
970 closed state upon failure.
971
972 The algorithm, known as a <em>composed asynchronous operation</em>, is
973 implemented in terms of calls to the underlying socket's `async_connect`
974 function.
975
976 If the timeout timer expires while the operation is outstanding,
977 the current connection attempt will be canceled and the completion
978 handler will be invoked with the error @ref error::timeout.
979
980 @param endpoints A sequence of endpoints. This this object must meet
981 the requirements of <em>EndpointSequence</em>.
982
983 @param handler The completion handler to invoke when the operation
984 completes. The implementation takes ownership of the handler by
985 performing a decay-copy. The equivalent function signature of
986 the handler must be:
987 @code
988 void handler(
989 // Result of operation. if the sequence is empty, set to
990 // net::error::not_found. Otherwise, contains the
991 // error from the last connection attempt.
992 error_code const& error,
993
994 // On success, the successfully connected endpoint.
995 // Otherwise, a default-constructed endpoint.
996 typename Protocol::endpoint const& endpoint
997 );
998 @endcode
999 If the handler has an associated immediate executor,
1000 an immediate completion will be dispatched to it.
1001 Otherwise, the handler will not be invoked from within
1002 this function. Invocation of the handler will be performed
1003 by dispatching to the immediate executor. If no
1004 immediate executor is specified, this is equivalent
1005 to using `net::post`.
1006
1007 @par Per-Operation Cancellation
1008
1009 This asynchronous operation supports cancellation for the following
1010 net::cancellation_type values:
1011
1012 @li @c net::cancellation_type::terminal
1013 @li @c net::cancellation_type::partial
1014 @li @c net::cancellation_type::total
1015
1016 if they are also supported by the socket's @c async_connect operation.
1017
1018 */
1019 template<
1020 class EndpointSequence,
1021 BOOST_ASIO_COMPLETION_TOKEN_FOR(
1022 void(error_code, typename Protocol::endpoint))
1023 RangeConnectHandler =
1024 net::default_completion_token_t<executor_type>
1025 #if ! BOOST_BEAST_DOXYGEN
1026 ,class = typename std::enable_if<
1027 net::is_endpoint_sequence<
1028 EndpointSequence>::value>::type
1029 #endif
1030 >
1031 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
1032 RangeConnectHandler,
1033 void(error_code, typename Protocol::endpoint))
1034 async_connect(
1035 EndpointSequence const& endpoints,
1036 RangeConnectHandler&& handler =
1037 net::default_completion_token_t<executor_type>{});
1038
1039 /** Establishes a connection by trying each endpoint in a sequence asynchronously.
1040
1041 This function attempts to connect the stream to one of a sequence of
1042 endpoints by trying each endpoint until a connection is successfully
1043 established.
1044 The underlying socket is automatically opened if needed.
1045 An automatically opened socket is not returned to the
1046 closed state upon failure.
1047
1048 The algorithm, known as a <em>composed asynchronous operation</em>, is
1049 implemented in terms of calls to the underlying socket's `async_connect`
1050 function.
1051
1052 If the timeout timer expires while the operation is outstanding,
1053 the current connection attempt will be canceled and the completion
1054 handler will be invoked with the error @ref error::timeout.
1055
1056 @param endpoints A sequence of endpoints. This this object must meet
1057 the requirements of <em>EndpointSequence</em>.
1058
1059 @param connect_condition A function object that is called prior to each
1060 connection attempt. The signature of the function object must be:
1061 @code
1062 bool connect_condition(
1063 error_code const& ec,
1064 typename Protocol::endpoint const& next);
1065 @endcode
1066 The @c ec parameter contains the result from the most recent connect
1067 operation. Before the first connection attempt, @c ec is always set to
1068 indicate success. The @c next parameter is the next endpoint to be tried.
1069 The function object should return true if the next endpoint should be tried,
1070 and false if it should be skipped.
1071
1072 @param handler The completion handler to invoke when the operation
1073 completes. The implementation takes ownership of the handler by
1074 performing a decay-copy. The equivalent function signature of
1075 the handler must be:
1076 @code
1077 void handler(
1078 // Result of operation. if the sequence is empty, set to
1079 // net::error::not_found. Otherwise, contains the
1080 // error from the last connection attempt.
1081 error_code const& error,
1082
1083 // On success, the successfully connected endpoint.
1084 // Otherwise, a default-constructed endpoint.
1085 typename Protocol::endpoint const& endpoint
1086 );
1087 @endcode
1088 If the handler has an associated immediate executor,
1089 an immediate completion will be dispatched to it.
1090 Otherwise, the handler will not be invoked from within
1091 this function. Invocation of the handler will be performed
1092 by dispatching to the immediate executor. If no
1093 immediate executor is specified, this is equivalent
1094 to using `net::post`.
1095 @par Example
1096 The following connect condition function object can be used to output
1097 information about the individual connection attempts:
1098 @code
1099 struct my_connect_condition
1100 {
1101 bool operator()(
1102 error_code const& ec,
1103 net::ip::tcp::endpoint const& next)
1104 {
1105 if (ec)
1106 std::cout << "Error: " << ec.message() << std::endl;
1107 std::cout << "Trying: " << next << std::endl;
1108 return true;
1109 }
1110 };
1111 @endcode
1112
1113 @par Per-Operation Cancellation
1114
1115 This asynchronous operation supports cancellation for the following
1116 net::cancellation_type values:
1117
1118 @li @c net::cancellation_type::terminal
1119 @li @c net::cancellation_type::partial
1120 @li @c net::cancellation_type::total
1121
1122 if they are also supported by the socket's @c async_connect operation.
1123 */
1124 template<
1125 class EndpointSequence,
1126 class ConnectCondition,
1127 BOOST_ASIO_COMPLETION_TOKEN_FOR(
1128 void(error_code, typename Protocol::endpoint))
1129 RangeConnectHandler =
1130 net::default_completion_token_t<executor_type>
1131 #if ! BOOST_BEAST_DOXYGEN
1132 ,class = typename std::enable_if<
1133 net::is_endpoint_sequence<
1134 EndpointSequence>::value>::type
1135 #endif
1136 >
1137 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
1138 RangeConnectHandler,
1139 void(error_code, typename Protocol::endpoint))
1140 async_connect(
1141 EndpointSequence const& endpoints,
1142 ConnectCondition connect_condition,
1143 RangeConnectHandler&& handler =
1144 net::default_completion_token_t<
1145 executor_type>{});
1146
1147 /** Establishes a connection by trying each endpoint in a sequence asynchronously.
1148
1149 This function attempts to connect the stream to one of a sequence of
1150 endpoints by trying each endpoint until a connection is successfully
1151 established.
1152 The underlying socket is automatically opened if needed.
1153 An automatically opened socket is not returned to the
1154 closed state upon failure.
1155
1156 The algorithm, known as a <em>composed asynchronous operation</em>, is
1157 implemented in terms of calls to the underlying socket's `async_connect`
1158 function.
1159
1160 If the timeout timer expires while the operation is outstanding,
1161 the current connection attempt will be canceled and the completion
1162 handler will be invoked with the error @ref error::timeout.
1163
1164 @param begin An iterator pointing to the start of a sequence of endpoints.
1165
1166 @param end An iterator pointing to the end of a sequence of endpoints.
1167
1168 @param handler The completion handler to invoke when the operation
1169 completes. The implementation takes ownership of the handler by
1170 performing a decay-copy. The equivalent function signature of
1171 the handler must be:
1172 @code
1173 void handler(
1174 // Result of operation. if the sequence is empty, set to
1175 // net::error::not_found. Otherwise, contains the
1176 // error from the last connection attempt.
1177 error_code const& error,
1178
1179 // On success, an iterator denoting the successfully
1180 // connected endpoint. Otherwise, the end iterator.
1181 Iterator iterator
1182 );
1183 @endcode
1184 If the handler has an associated immediate executor,
1185 an immediate completion will be dispatched to it.
1186 Otherwise, the handler will not be invoked from within
1187 this function. Invocation of the handler will be performed
1188 by dispatching to the immediate executor. If no
1189 immediate executor is specified, this is equivalent
1190 to using `net::post`.
1191 @par Per-Operation Cancellation
1192
1193 This asynchronous operation supports cancellation for the following
1194 net::cancellation_type values:
1195
1196 @li @c net::cancellation_type::terminal
1197 @li @c net::cancellation_type::partial
1198 @li @c net::cancellation_type::total
1199
1200 if they are also supported by the socket's @c async_connect operation.
1201 */
1202 template<
1203 class Iterator,
1204 BOOST_ASIO_COMPLETION_TOKEN_FOR(
1205 void(error_code, Iterator))
1206 IteratorConnectHandler =
1207 net::default_completion_token_t<executor_type>>
1208 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
1209 IteratorConnectHandler,
1210 void(error_code, Iterator))
1211 async_connect(
1212 Iterator begin, Iterator end,
1213 IteratorConnectHandler&& handler =
1214 net::default_completion_token_t<executor_type>{});
1215
1216 /** Establishes a connection by trying each endpoint in a sequence asynchronously.
1217
1218 This function attempts to connect the stream to one of a sequence of
1219 endpoints by trying each endpoint until a connection is successfully
1220 established.
1221 The algorithm, known as a <em>composed asynchronous operation</em>, is
1222 implemented in terms of calls to the underlying socket's `async_connect`
1223 function.
1224
1225 If the timeout timer expires while the operation is outstanding,
1226 the current connection attempt will be canceled and the completion
1227 handler will be invoked with the error @ref error::timeout.
1228
1229 @param begin An iterator pointing to the start of a sequence of endpoints.
1230
1231 @param end An iterator pointing to the end of a sequence of endpoints.
1232
1233 @param connect_condition A function object that is called prior to each
1234 connection attempt. The signature of the function object must be:
1235 @code
1236 bool connect_condition(
1237 error_code const& ec,
1238 typename Protocol::endpoint const& next);
1239 @endcode
1240
1241 @param handler The completion handler to invoke when the operation
1242 completes. The implementation takes ownership of the handler by
1243 performing a decay-copy. The equivalent function signature of
1244 the handler must be:
1245 @code
1246 void handler(
1247 // Result of operation. if the sequence is empty, set to
1248 // net::error::not_found. Otherwise, contains the
1249 // error from the last connection attempt.
1250 error_code const& error,
1251
1252 // On success, an iterator denoting the successfully
1253 // connected endpoint. Otherwise, the end iterator.
1254 Iterator iterator
1255 );
1256 @endcode
1257 If the handler has an associated immediate executor,
1258 an immediate completion will be dispatched to it.
1259 Otherwise, the handler will not be invoked from within
1260 this function. Invocation of the handler will be performed
1261 by dispatching to the immediate executor. If no
1262 immediate executor is specified, this is equivalent
1263 to using `net::post`.
1264 @par Per-Operation Cancellation
1265
1266 This asynchronous operation supports cancellation for the following
1267 net::cancellation_type values:
1268
1269 @li @c net::cancellation_type::terminal
1270 @li @c net::cancellation_type::partial
1271 @li @c net::cancellation_type::total
1272
1273 if they are also supported by the socket's @c async_connect operation.
1274 */
1275 template<
1276 class Iterator,
1277 class ConnectCondition,
1278 BOOST_ASIO_COMPLETION_TOKEN_FOR(
1279 void(error_code, Iterator))
1280 IteratorConnectHandler =
1281 net::default_completion_token_t<executor_type>>
1282 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
1283 IteratorConnectHandler,
1284 void(error_code, Iterator))
1285 async_connect(
1286 Iterator begin, Iterator end,
1287 ConnectCondition connect_condition,
1288 IteratorConnectHandler&& handler =
1289 net::default_completion_token_t<executor_type>{});
1290
1291 //--------------------------------------------------------------------------
1292
1293 /** Read some data.
1294
1295 This function is used to read some data from the stream.
1296
1297 The call blocks until one of the following is true:
1298
1299 @li One or more bytes are read from the stream.
1300
1301 @li An error occurs.
1302
1303 @param buffers The buffers into which the data will be read. If the
1304 size of the buffers is zero bytes, the call always returns
1305 immediately with no error.
1306
1307 @returns The number of bytes read.
1308
1309 @throws system_error Thrown on failure.
1310
1311 @note The `read_some` operation may not receive all of the requested
1312 number of bytes. Consider using the function `net::read` if you need
1313 to ensure that the requested amount of data is read before the
1314 blocking operation completes.
1315 */
1316 template<class MutableBufferSequence>
1317 std::size_t
1318 read_some(MutableBufferSequence const& buffers)
1319 {
1320 return impl_->socket.read_some(buffers);
1321 }
1322
1323 /** Read some data.
1324
1325 This function is used to read some data from the underlying socket.
1326
1327 The call blocks until one of the following is true:
1328
1329 @li One or more bytes are read from the stream.
1330
1331 @li An error occurs.
1332
1333 @param buffers The buffers into which the data will be read. If the
1334 size of the buffers is zero bytes, the call always returns
1335 immediately with no error.
1336
1337 @param ec Set to indicate what error occurred, if any.
1338
1339 @returns The number of bytes read.
1340
1341 @note The `read_some` operation may not receive all of the requested
1342 number of bytes. Consider using the function `net::read` if you need
1343 to ensure that the requested amount of data is read before the
1344 blocking operation completes.
1345 */
1346 template<class MutableBufferSequence>
1347 std::size_t
1348 read_some(
1349 MutableBufferSequence const& buffers,
1350 error_code& ec)
1351 {
1352 return impl_->socket.read_some(buffers, ec);
1353 }
1354
1355 /** Read some data asynchronously.
1356
1357 This function is used to asynchronously read data from the stream.
1358
1359 This call always returns immediately. The asynchronous operation
1360 will continue until one of the following conditions is true:
1361
1362 @li One or more bytes are read from the stream.
1363
1364 @li An error occurs.
1365
1366 The algorithm, known as a <em>composed asynchronous operation</em>,
1367 is implemented in terms of calls to the next layer's `async_read_some`
1368 function. The program must ensure that no other calls to @ref read_some
1369 or @ref async_read_some are performed until this operation completes.
1370
1371 If the timeout timer expires while the operation is outstanding,
1372 the operation will be canceled and the completion handler will be
1373 invoked with the error @ref error::timeout.
1374
1375 @param buffers The buffers into which the data will be read. If the size
1376 of the buffers is zero bytes, the operation always completes immediately
1377 with no error.
1378 Although the buffers object may be copied as necessary, ownership of the
1379 underlying memory blocks is retained by the caller, which must guarantee
1380 that they remain valid until the handler is called.
1381
1382 @param handler The completion handler to invoke when the operation
1383 completes. The implementation takes ownership of the handler by
1384 performing a decay-copy. The equivalent function signature of
1385 the handler must be:
1386 @code
1387 void handler(
1388 error_code error, // Result of operation.
1389 std::size_t bytes_transferred // Number of bytes read.
1390 );
1391 @endcode
1392 If the handler has an associated immediate executor,
1393 an immediate completion will be dispatched to it.
1394 Otherwise, the handler will not be invoked from within
1395 this function. Invocation of the handler will be performed
1396 by dispatching to the immediate executor. If no
1397 immediate executor is specified, this is equivalent
1398 to using `net::post`.
1399 @note The `async_read_some` operation may not receive all of the requested
1400 number of bytes. Consider using the function `net::async_read` if you need
1401 to ensure that the requested amount of data is read before the asynchronous
1402 operation completes.
1403
1404 @par Per-Operation Cancellation
1405
1406 This asynchronous operation supports cancellation for the following
1407 net::cancellation_type values:
1408
1409 @li @c net::cancellation_type::terminal
1410 @li @c net::cancellation_type::partial
1411 @li @c net::cancellation_type::total
1412
1413 if they are also supported by the socket's @c async_read_some operation.
1414 */
1415 template<
1416 class MutableBufferSequence,
1417 BOOST_BEAST_ASYNC_TPARAM2 ReadHandler =
1418 net::default_completion_token_t<executor_type>
1419 >
1420 BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
1421 async_read_some(
1422 MutableBufferSequence const& buffers,
1423 ReadHandler&& handler =
1424 net::default_completion_token_t<executor_type>{}
1425 );
1426
1427 /** Write some data.
1428
1429 This function is used to write some data to the stream.
1430
1431 The call blocks until one of the following is true:
1432
1433 @li One or more bytes are written to the stream.
1434
1435 @li An error occurs.
1436
1437 @param buffers The buffers from which the data will be written. If the
1438 size of the buffers is zero bytes, the call always returns immediately
1439 with no error.
1440
1441 @returns The number of bytes written.
1442
1443 @throws system_error Thrown on failure.
1444
1445 @note The `write_some` operation may not transmit all of the requested
1446 number of bytes. Consider using the function `net::write` if you need
1447 to ensure that the requested amount of data is written before the
1448 blocking operation completes.
1449 */
1450 template<class ConstBufferSequence>
1451 std::size_t
1452 write_some(ConstBufferSequence const& buffers)
1453 {
1454 return impl_->socket.write_some(buffers);
1455 }
1456
1457 /** Write some data.
1458
1459 This function is used to write some data to the stream.
1460
1461 The call blocks until one of the following is true:
1462
1463 @li One or more bytes are written to the stream.
1464
1465 @li An error occurs.
1466
1467 @param buffers The buffers from which the data will be written. If the
1468 size of the buffers is zero bytes, the call always returns immediately
1469 with no error.
1470
1471 @param ec Set to indicate what error occurred, if any.
1472
1473 @returns The number of bytes written.
1474
1475 @throws system_error Thrown on failure.
1476
1477 @note The `write_some` operation may not transmit all of the requested
1478 number of bytes. Consider using the function `net::write` if you need
1479 to ensure that the requested amount of data is written before the
1480 blocking operation completes.
1481 */
1482 template<class ConstBufferSequence>
1483 std::size_t
1484 write_some(
1485 ConstBufferSequence const& buffers,
1486 error_code& ec)
1487 {
1488 return impl_->socket.write_some(buffers, ec);
1489 }
1490
1491 /** Write some data asynchronously.
1492
1493 This function is used to asynchronously write data to the underlying socket.
1494
1495 This call always returns immediately. The asynchronous operation
1496 will continue until one of the following conditions is true:
1497
1498 @li One or more bytes are written to the stream.
1499
1500 @li An error occurs.
1501
1502 The algorithm, known as a <em>composed asynchronous operation</em>,
1503 is implemented in terms of calls to the next layer's `async_write_some`
1504 function. The program must ensure that no other calls to @ref async_write_some
1505 are performed until this operation completes.
1506
1507 If the timeout timer expires while the operation is outstanding,
1508 the operation will be canceled and the completion handler will be
1509 invoked with the error @ref error::timeout.
1510
1511 @param buffers The buffers from which the data will be written. If the
1512 size of the buffers is zero bytes, the operation always completes
1513 immediately with no error.
1514 Although the buffers object may be copied as necessary, ownership of the
1515 underlying memory blocks is retained by the caller, which must guarantee
1516 that they remain valid until the handler is called.
1517
1518 @param handler The completion handler to invoke when the operation
1519 completes. The implementation takes ownership of the handler by
1520 performing a decay-copy. The equivalent function signature of
1521 the handler must be:
1522 @code
1523 void handler(
1524 error_code error, // Result of operation.
1525 std::size_t bytes_transferred // Number of bytes written.
1526 );
1527 @endcode
1528 If the handler has an associated immediate executor,
1529 an immediate completion will be dispatched to it.
1530 Otherwise, the handler will not be invoked from within
1531 this function. Invocation of the handler will be performed
1532 by dispatching to the immediate executor. If no
1533 immediate executor is specified, this is equivalent
1534 to using `net::post`.
1535 @note The `async_write_some` operation may not transmit all of the requested
1536 number of bytes. Consider using the function `net::async_write` if you need
1537 to ensure that the requested amount of data is sent before the asynchronous
1538 operation completes.
1539
1540 @par Per-Operation Cancellation
1541
1542 This asynchronous operation supports cancellation for the following
1543 net::cancellation_type values:
1544
1545 @li @c net::cancellation_type::terminal
1546 @li @c net::cancellation_type::partial
1547 @li @c net::cancellation_type::total
1548
1549 if they are also supported by the socket's @c async_write_some operation.
1550 */
1551 template<
1552 class ConstBufferSequence,
1553 BOOST_BEAST_ASYNC_TPARAM2 WriteHandler =
1554 net::default_completion_token_t<Executor>
1555 >
1556 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
1557 async_write_some(
1558 ConstBufferSequence const& buffers,
1559 WriteHandler&& handler =
1560 net::default_completion_token_t<Executor>{});
1561};
1562
1563} // beast
1564} // boost
1565
1566#include <boost/beast/core/impl/basic_stream.hpp>
1567
1568#endif
1569

source code of boost/libs/beast/include/boost/beast/core/basic_stream.hpp