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> exboost::beast::basic_stream::impl_type275 ex() noexcept 276 { 277 return this->socket.get_executor(); 278 } 279 280 RatePolicy& policyboost::beast::basic_stream::impl_type281 policy() noexcept 282 { 283 return this->boost::empty_value<RatePolicy>::get(); 284 } 285 286 RatePolicy const& policyboost::beast::basic_stream::impl_type287 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& lowest_layer()319 lowest_layer() noexcept 320 { 321 return impl_->socket; 322 } 323 // DEPRECATED 324 lowest_layer_type const& lowest_layer() const325 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& socket()401 socket() noexcept 402 { 403 return impl_->socket; 404 } 405 406 /// Return a reference to the underlying socket 407 socket_type const& socket() const408 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& rate_policy()427 rate_policy() noexcept 428 { 429 return impl_->policy(); 430 } 431 432 /// Returns the rate policy associated with the object 433 RatePolicy const& rate_policy() const434 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 get_executor()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 connect(endpoint_type const & ep)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 connect(endpoint_type const & ep,error_code & ec)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 connect(EndpointSequence const & endpoints)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 connect(EndpointSequence const & endpoints,error_code & ec)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 connect(Iterator begin,Iterator end)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 connect(Iterator begin,Iterator end,error_code & ec)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 connect(EndpointSequence const & endpoints,ConnectCondition connect_condition)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 connect(EndpointSequence const & endpoints,ConnectCondition connect_condition,error_code & ec)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 read_some(MutableBufferSequence const & buffers)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 read_some(MutableBufferSequence const & buffers,error_code & ec)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 write_some(ConstBufferSequence const & buffers)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 write_some(ConstBufferSequence const & buffers,error_code & ec)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 1461