1 // 2 // ssl/stream.hpp 3 // ~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 // 7 // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 // 10 11 #ifndef BOOST_ASIO_SSL_STREAM_HPP 12 #define BOOST_ASIO_SSL_STREAM_HPP 13 14 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 15 # pragma once 16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 17 18 #include <boost/asio/detail/config.hpp> 19 20 #include <boost/asio/async_result.hpp> 21 #include <boost/asio/detail/buffer_sequence_adapter.hpp> 22 #include <boost/asio/detail/handler_type_requirements.hpp> 23 #include <boost/asio/detail/non_const_lvalue.hpp> 24 #include <boost/asio/detail/noncopyable.hpp> 25 #include <boost/asio/detail/type_traits.hpp> 26 #include <boost/asio/ssl/context.hpp> 27 #include <boost/asio/ssl/detail/buffered_handshake_op.hpp> 28 #include <boost/asio/ssl/detail/handshake_op.hpp> 29 #include <boost/asio/ssl/detail/io.hpp> 30 #include <boost/asio/ssl/detail/read_op.hpp> 31 #include <boost/asio/ssl/detail/shutdown_op.hpp> 32 #include <boost/asio/ssl/detail/stream_core.hpp> 33 #include <boost/asio/ssl/detail/write_op.hpp> 34 #include <boost/asio/ssl/stream_base.hpp> 35 36 #include <boost/asio/detail/push_options.hpp> 37 38 namespace boost { 39 namespace asio { 40 namespace ssl { 41 42 /// Provides stream-oriented functionality using SSL. 43 /** 44 * The stream class template provides asynchronous and blocking stream-oriented 45 * functionality using SSL. 46 * 47 * @par Thread Safety 48 * @e Distinct @e objects: Safe.@n 49 * @e Shared @e objects: Unsafe. The application must also ensure that all 50 * asynchronous operations are performed within the same implicit or explicit 51 * strand. 52 * 53 * @par Example 54 * To use the SSL stream template with an ip::tcp::socket, you would write: 55 * @code 56 * boost::asio::io_context my_context; 57 * boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); 58 * boost::asio::ssl::stream<asio:ip::tcp::socket> sock(my_context, ctx); 59 * @endcode 60 * 61 * @par Concepts: 62 * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. 63 */ 64 template <typename Stream> 65 class stream : 66 public stream_base, 67 private noncopyable 68 { 69 public: 70 /// The native handle type of the SSL stream. 71 typedef SSL* native_handle_type; 72 73 /// Structure for use with deprecated impl_type. 74 struct impl_struct 75 { 76 SSL* ssl; 77 }; 78 79 /// The type of the next layer. 80 typedef typename remove_reference<Stream>::type next_layer_type; 81 82 /// The type of the lowest layer. 83 typedef typename next_layer_type::lowest_layer_type lowest_layer_type; 84 85 /// The type of the executor associated with the object. 86 typedef typename lowest_layer_type::executor_type executor_type; 87 88 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 89 /// Construct a stream. 90 /** 91 * This constructor creates a stream and initialises the underlying stream 92 * object. 93 * 94 * @param arg The argument to be passed to initialise the underlying stream. 95 * 96 * @param ctx The SSL context to be used for the stream. 97 */ 98 template <typename Arg> stream(Arg && arg,context & ctx)99 stream(Arg&& arg, context& ctx) 100 : next_layer_(BOOST_ASIO_MOVE_CAST(Arg)(arg)), 101 core_(ctx.native_handle(), next_layer_.lowest_layer().get_executor()) 102 { 103 } 104 #else // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 105 template <typename Arg> stream(Arg & arg,context & ctx)106 stream(Arg& arg, context& ctx) 107 : next_layer_(arg), 108 core_(ctx.native_handle(), next_layer_.lowest_layer().get_executor()) 109 { 110 } 111 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 112 113 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 114 /// Move-construct a stream from another. 115 /** 116 * @param other The other stream object from which the move will occur. Must 117 * have no outstanding asynchronous operations associated with it. Following 118 * the move, @c other has a valid but unspecified state where the only safe 119 * operation is destruction. 120 */ stream(stream && other)121 stream(stream&& other) 122 : next_layer_(BOOST_ASIO_MOVE_CAST(Stream)(other.next_layer_)), 123 core_(BOOST_ASIO_MOVE_CAST(detail::stream_core)(other.core_)) 124 { 125 } 126 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 127 128 /// Destructor. 129 /** 130 * @note A @c stream object must not be destroyed while there are pending 131 * asynchronous operations associated with it. 132 */ ~stream()133 ~stream() 134 { 135 } 136 137 /// Get the executor associated with the object. 138 /** 139 * This function may be used to obtain the executor object that the stream 140 * uses to dispatch handlers for asynchronous operations. 141 * 142 * @return A copy of the executor that stream will use to dispatch handlers. 143 */ get_executor()144 executor_type get_executor() BOOST_ASIO_NOEXCEPT 145 { 146 return next_layer_.lowest_layer().get_executor(); 147 } 148 149 /// Get the underlying implementation in the native type. 150 /** 151 * This function may be used to obtain the underlying implementation of the 152 * context. This is intended to allow access to context functionality that is 153 * not otherwise provided. 154 * 155 * @par Example 156 * The native_handle() function returns a pointer of type @c SSL* that is 157 * suitable for passing to functions such as @c SSL_get_verify_result and 158 * @c SSL_get_peer_certificate: 159 * @code 160 * boost::asio::ssl::stream<asio:ip::tcp::socket> sock(my_context, ctx); 161 * 162 * // ... establish connection and perform handshake ... 163 * 164 * if (X509* cert = SSL_get_peer_certificate(sock.native_handle())) 165 * { 166 * if (SSL_get_verify_result(sock.native_handle()) == X509_V_OK) 167 * { 168 * // ... 169 * } 170 * } 171 * @endcode 172 */ native_handle()173 native_handle_type native_handle() 174 { 175 return core_.engine_.native_handle(); 176 } 177 178 /// Get a reference to the next layer. 179 /** 180 * This function returns a reference to the next layer in a stack of stream 181 * layers. 182 * 183 * @return A reference to the next layer in the stack of stream layers. 184 * Ownership is not transferred to the caller. 185 */ next_layer() const186 const next_layer_type& next_layer() const 187 { 188 return next_layer_; 189 } 190 191 /// Get a reference to the next layer. 192 /** 193 * This function returns a reference to the next layer in a stack of stream 194 * layers. 195 * 196 * @return A reference to the next layer in the stack of stream layers. 197 * Ownership is not transferred to the caller. 198 */ next_layer()199 next_layer_type& next_layer() 200 { 201 return next_layer_; 202 } 203 204 /// Get a reference to the lowest layer. 205 /** 206 * This function returns a reference to the lowest layer in a stack of 207 * stream layers. 208 * 209 * @return A reference to the lowest layer in the stack of stream layers. 210 * Ownership is not transferred to the caller. 211 */ lowest_layer()212 lowest_layer_type& lowest_layer() 213 { 214 return next_layer_.lowest_layer(); 215 } 216 217 /// Get a reference to the lowest layer. 218 /** 219 * This function returns a reference to the lowest layer in a stack of 220 * stream layers. 221 * 222 * @return A reference to the lowest layer in the stack of stream layers. 223 * Ownership is not transferred to the caller. 224 */ lowest_layer() const225 const lowest_layer_type& lowest_layer() const 226 { 227 return next_layer_.lowest_layer(); 228 } 229 230 /// Set the peer verification mode. 231 /** 232 * This function may be used to configure the peer verification mode used by 233 * the stream. The new mode will override the mode inherited from the context. 234 * 235 * @param v A bitmask of peer verification modes. See @ref verify_mode for 236 * available values. 237 * 238 * @throws boost::system::system_error Thrown on failure. 239 * 240 * @note Calls @c SSL_set_verify. 241 */ set_verify_mode(verify_mode v)242 void set_verify_mode(verify_mode v) 243 { 244 boost::system::error_code ec; 245 set_verify_mode(v, ec); 246 boost::asio::detail::throw_error(ec, "set_verify_mode"); 247 } 248 249 /// Set the peer verification mode. 250 /** 251 * This function may be used to configure the peer verification mode used by 252 * the stream. The new mode will override the mode inherited from the context. 253 * 254 * @param v A bitmask of peer verification modes. See @ref verify_mode for 255 * available values. 256 * 257 * @param ec Set to indicate what error occurred, if any. 258 * 259 * @note Calls @c SSL_set_verify. 260 */ set_verify_mode(verify_mode v,boost::system::error_code & ec)261 BOOST_ASIO_SYNC_OP_VOID set_verify_mode( 262 verify_mode v, boost::system::error_code& ec) 263 { 264 core_.engine_.set_verify_mode(v, ec); 265 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 266 } 267 268 /// Set the peer verification depth. 269 /** 270 * This function may be used to configure the maximum verification depth 271 * allowed by the stream. 272 * 273 * @param depth Maximum depth for the certificate chain verification that 274 * shall be allowed. 275 * 276 * @throws boost::system::system_error Thrown on failure. 277 * 278 * @note Calls @c SSL_set_verify_depth. 279 */ set_verify_depth(int depth)280 void set_verify_depth(int depth) 281 { 282 boost::system::error_code ec; 283 set_verify_depth(depth, ec); 284 boost::asio::detail::throw_error(ec, "set_verify_depth"); 285 } 286 287 /// Set the peer verification depth. 288 /** 289 * This function may be used to configure the maximum verification depth 290 * allowed by the stream. 291 * 292 * @param depth Maximum depth for the certificate chain verification that 293 * shall be allowed. 294 * 295 * @param ec Set to indicate what error occurred, if any. 296 * 297 * @note Calls @c SSL_set_verify_depth. 298 */ set_verify_depth(int depth,boost::system::error_code & ec)299 BOOST_ASIO_SYNC_OP_VOID set_verify_depth( 300 int depth, boost::system::error_code& ec) 301 { 302 core_.engine_.set_verify_depth(depth, ec); 303 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 304 } 305 306 /// Set the callback used to verify peer certificates. 307 /** 308 * This function is used to specify a callback function that will be called 309 * by the implementation when it needs to verify a peer certificate. 310 * 311 * @param callback The function object to be used for verifying a certificate. 312 * The function signature of the handler must be: 313 * @code bool verify_callback( 314 * bool preverified, // True if the certificate passed pre-verification. 315 * verify_context& ctx // The peer certificate and other context. 316 * ); @endcode 317 * The return value of the callback is true if the certificate has passed 318 * verification, false otherwise. 319 * 320 * @throws boost::system::system_error Thrown on failure. 321 * 322 * @note Calls @c SSL_set_verify. 323 */ 324 template <typename VerifyCallback> set_verify_callback(VerifyCallback callback)325 void set_verify_callback(VerifyCallback callback) 326 { 327 boost::system::error_code ec; 328 this->set_verify_callback(callback, ec); 329 boost::asio::detail::throw_error(ec, "set_verify_callback"); 330 } 331 332 /// Set the callback used to verify peer certificates. 333 /** 334 * This function is used to specify a callback function that will be called 335 * by the implementation when it needs to verify a peer certificate. 336 * 337 * @param callback The function object to be used for verifying a certificate. 338 * The function signature of the handler must be: 339 * @code bool verify_callback( 340 * bool preverified, // True if the certificate passed pre-verification. 341 * verify_context& ctx // The peer certificate and other context. 342 * ); @endcode 343 * The return value of the callback is true if the certificate has passed 344 * verification, false otherwise. 345 * 346 * @param ec Set to indicate what error occurred, if any. 347 * 348 * @note Calls @c SSL_set_verify. 349 */ 350 template <typename VerifyCallback> set_verify_callback(VerifyCallback callback,boost::system::error_code & ec)351 BOOST_ASIO_SYNC_OP_VOID set_verify_callback(VerifyCallback callback, 352 boost::system::error_code& ec) 353 { 354 core_.engine_.set_verify_callback( 355 new detail::verify_callback<VerifyCallback>(callback), ec); 356 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 357 } 358 359 /// Perform SSL handshaking. 360 /** 361 * This function is used to perform SSL handshaking on the stream. The 362 * function call will block until handshaking is complete or an error occurs. 363 * 364 * @param type The type of handshaking to be performed, i.e. as a client or as 365 * a server. 366 * 367 * @throws boost::system::system_error Thrown on failure. 368 */ handshake(handshake_type type)369 void handshake(handshake_type type) 370 { 371 boost::system::error_code ec; 372 handshake(type, ec); 373 boost::asio::detail::throw_error(ec, "handshake"); 374 } 375 376 /// Perform SSL handshaking. 377 /** 378 * This function is used to perform SSL handshaking on the stream. The 379 * function call will block until handshaking is complete or an error occurs. 380 * 381 * @param type The type of handshaking to be performed, i.e. as a client or as 382 * a server. 383 * 384 * @param ec Set to indicate what error occurred, if any. 385 */ handshake(handshake_type type,boost::system::error_code & ec)386 BOOST_ASIO_SYNC_OP_VOID handshake(handshake_type type, 387 boost::system::error_code& ec) 388 { 389 detail::io(next_layer_, core_, detail::handshake_op(type), ec); 390 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 391 } 392 393 /// Perform SSL handshaking. 394 /** 395 * This function is used to perform SSL handshaking on the stream. The 396 * function call will block until handshaking is complete or an error occurs. 397 * 398 * @param type The type of handshaking to be performed, i.e. as a client or as 399 * a server. 400 * 401 * @param buffers The buffered data to be reused for the handshake. 402 * 403 * @throws boost::system::system_error Thrown on failure. 404 */ 405 template <typename ConstBufferSequence> handshake(handshake_type type,const ConstBufferSequence & buffers)406 void handshake(handshake_type type, const ConstBufferSequence& buffers) 407 { 408 boost::system::error_code ec; 409 handshake(type, buffers, ec); 410 boost::asio::detail::throw_error(ec, "handshake"); 411 } 412 413 /// Perform SSL handshaking. 414 /** 415 * This function is used to perform SSL handshaking on the stream. The 416 * function call will block until handshaking is complete or an error occurs. 417 * 418 * @param type The type of handshaking to be performed, i.e. as a client or as 419 * a server. 420 * 421 * @param buffers The buffered data to be reused for the handshake. 422 * 423 * @param ec Set to indicate what error occurred, if any. 424 */ 425 template <typename ConstBufferSequence> handshake(handshake_type type,const ConstBufferSequence & buffers,boost::system::error_code & ec)426 BOOST_ASIO_SYNC_OP_VOID handshake(handshake_type type, 427 const ConstBufferSequence& buffers, boost::system::error_code& ec) 428 { 429 detail::io(next_layer_, core_, 430 detail::buffered_handshake_op<ConstBufferSequence>(type, buffers), ec); 431 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 432 } 433 434 /// Start an asynchronous SSL handshake. 435 /** 436 * This function is used to asynchronously perform an SSL handshake on the 437 * stream. This function call always returns immediately. 438 * 439 * @param type The type of handshaking to be performed, i.e. as a client or as 440 * a server. 441 * 442 * @param handler The handler to be called when the handshake operation 443 * completes. Copies will be made of the handler as required. The equivalent 444 * function signature of the handler must be: 445 * @code void handler( 446 * const boost::system::error_code& error // Result of operation. 447 * ); @endcode 448 */ 449 template < 450 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code)) 451 HandshakeHandler 452 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(HandshakeHandler,void (boost::system::error_code))453 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(HandshakeHandler, 454 void (boost::system::error_code)) 455 async_handshake(handshake_type type, 456 BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler 457 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) 458 { 459 return async_initiate<HandshakeHandler, 460 void (boost::system::error_code)>( 461 initiate_async_handshake(this), handler, type); 462 } 463 464 /// Start an asynchronous SSL handshake. 465 /** 466 * This function is used to asynchronously perform an SSL handshake on the 467 * stream. This function call always returns immediately. 468 * 469 * @param type The type of handshaking to be performed, i.e. as a client or as 470 * a server. 471 * 472 * @param buffers The buffered data to be reused for the handshake. Although 473 * the buffers object may be copied as necessary, ownership of the underlying 474 * buffers is retained by the caller, which must guarantee that they remain 475 * valid until the handler is called. 476 * 477 * @param handler The handler to be called when the handshake operation 478 * completes. Copies will be made of the handler as required. The equivalent 479 * function signature of the handler must be: 480 * @code void handler( 481 * const boost::system::error_code& error, // Result of operation. 482 * std::size_t bytes_transferred // Amount of buffers used in handshake. 483 * ); @endcode 484 */ 485 template <typename ConstBufferSequence, 486 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, 487 std::size_t)) BufferedHandshakeHandler 488 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(BufferedHandshakeHandler,void (boost::system::error_code,std::size_t))489 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(BufferedHandshakeHandler, 490 void (boost::system::error_code, std::size_t)) 491 async_handshake(handshake_type type, const ConstBufferSequence& buffers, 492 BOOST_ASIO_MOVE_ARG(BufferedHandshakeHandler) handler 493 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) 494 { 495 return async_initiate<BufferedHandshakeHandler, 496 void (boost::system::error_code, std::size_t)>( 497 initiate_async_buffered_handshake(this), handler, type, buffers); 498 } 499 500 /// Shut down SSL on the stream. 501 /** 502 * This function is used to shut down SSL on the stream. The function call 503 * will block until SSL has been shut down or an error occurs. 504 * 505 * @throws boost::system::system_error Thrown on failure. 506 */ shutdown()507 void shutdown() 508 { 509 boost::system::error_code ec; 510 shutdown(ec); 511 boost::asio::detail::throw_error(ec, "shutdown"); 512 } 513 514 /// Shut down SSL on the stream. 515 /** 516 * This function is used to shut down SSL on the stream. The function call 517 * will block until SSL has been shut down or an error occurs. 518 * 519 * @param ec Set to indicate what error occurred, if any. 520 */ shutdown(boost::system::error_code & ec)521 BOOST_ASIO_SYNC_OP_VOID shutdown(boost::system::error_code& ec) 522 { 523 detail::io(next_layer_, core_, detail::shutdown_op(), ec); 524 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 525 } 526 527 /// Asynchronously shut down SSL on the stream. 528 /** 529 * This function is used to asynchronously shut down SSL on the stream. This 530 * function call always returns immediately. 531 * 532 * @param handler The handler to be called when the handshake operation 533 * completes. Copies will be made of the handler as required. The equivalent 534 * function signature of the handler must be: 535 * @code void handler( 536 * const boost::system::error_code& error // Result of operation. 537 * ); @endcode 538 */ 539 template < 540 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code)) 541 ShutdownHandler 542 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ShutdownHandler,void (boost::system::error_code))543 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ShutdownHandler, 544 void (boost::system::error_code)) 545 async_shutdown( 546 BOOST_ASIO_MOVE_ARG(ShutdownHandler) handler 547 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) 548 { 549 return async_initiate<ShutdownHandler, 550 void (boost::system::error_code)>( 551 initiate_async_shutdown(this), handler); 552 } 553 554 /// Write some data to the stream. 555 /** 556 * This function is used to write data on the stream. The function call will 557 * block until one or more bytes of data has been written successfully, or 558 * until an error occurs. 559 * 560 * @param buffers The data to be written. 561 * 562 * @returns The number of bytes written. 563 * 564 * @throws boost::system::system_error Thrown on failure. 565 * 566 * @note The write_some operation may not transmit all of the data to the 567 * peer. Consider using the @ref write function if you need to ensure that all 568 * data is written before the blocking operation completes. 569 */ 570 template <typename ConstBufferSequence> write_some(const ConstBufferSequence & buffers)571 std::size_t write_some(const ConstBufferSequence& buffers) 572 { 573 boost::system::error_code ec; 574 std::size_t n = write_some(buffers, ec); 575 boost::asio::detail::throw_error(ec, "write_some"); 576 return n; 577 } 578 579 /// Write some data to the stream. 580 /** 581 * This function is used to write data on the stream. The function call will 582 * block until one or more bytes of data has been written successfully, or 583 * until an error occurs. 584 * 585 * @param buffers The data to be written to the stream. 586 * 587 * @param ec Set to indicate what error occurred, if any. 588 * 589 * @returns The number of bytes written. Returns 0 if an error occurred. 590 * 591 * @note The write_some operation may not transmit all of the data to the 592 * peer. Consider using the @ref write function if you need to ensure that all 593 * data is written before the blocking operation completes. 594 */ 595 template <typename ConstBufferSequence> write_some(const ConstBufferSequence & buffers,boost::system::error_code & ec)596 std::size_t write_some(const ConstBufferSequence& buffers, 597 boost::system::error_code& ec) 598 { 599 return detail::io(next_layer_, core_, 600 detail::write_op<ConstBufferSequence>(buffers), ec); 601 } 602 603 /// Start an asynchronous write. 604 /** 605 * This function is used to asynchronously write one or more bytes of data to 606 * the stream. The function call always returns immediately. 607 * 608 * @param buffers The data to be written to the stream. Although the buffers 609 * object may be copied as necessary, ownership of the underlying buffers is 610 * retained by the caller, which must guarantee that they remain valid until 611 * the handler is called. 612 * 613 * @param handler The handler to be called when the write operation completes. 614 * Copies will be made of the handler as required. The equivalent function 615 * signature of the handler must be: 616 * @code void handler( 617 * const boost::system::error_code& error, // Result of operation. 618 * std::size_t bytes_transferred // Number of bytes written. 619 * ); @endcode 620 * 621 * @note The async_write_some operation may not transmit all of the data to 622 * the peer. Consider using the @ref async_write function if you need to 623 * ensure that all data is written before the asynchronous operation 624 * completes. 625 */ 626 template <typename ConstBufferSequence, 627 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, 628 std::size_t)) WriteHandler 629 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,void (boost::system::error_code,std::size_t))630 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, 631 void (boost::system::error_code, std::size_t)) 632 async_write_some(const ConstBufferSequence& buffers, 633 BOOST_ASIO_MOVE_ARG(WriteHandler) handler 634 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) 635 { 636 return async_initiate<WriteHandler, 637 void (boost::system::error_code, std::size_t)>( 638 initiate_async_write_some(this), handler, buffers); 639 } 640 641 /// Read some data from the stream. 642 /** 643 * This function is used to read data from the stream. The function call will 644 * block until one or more bytes of data has been read successfully, or until 645 * an error occurs. 646 * 647 * @param buffers The buffers into which the data will be read. 648 * 649 * @returns The number of bytes read. 650 * 651 * @throws boost::system::system_error Thrown on failure. 652 * 653 * @note The read_some operation may not read all of the requested number of 654 * bytes. Consider using the @ref read function if you need to ensure that the 655 * requested amount of data is read before the blocking operation completes. 656 */ 657 template <typename MutableBufferSequence> read_some(const MutableBufferSequence & buffers)658 std::size_t read_some(const MutableBufferSequence& buffers) 659 { 660 boost::system::error_code ec; 661 std::size_t n = read_some(buffers, ec); 662 boost::asio::detail::throw_error(ec, "read_some"); 663 return n; 664 } 665 666 /// Read some data from the stream. 667 /** 668 * This function is used to read data from the stream. The function call will 669 * block until one or more bytes of data has been read successfully, or until 670 * an error occurs. 671 * 672 * @param buffers The buffers into which the data will be read. 673 * 674 * @param ec Set to indicate what error occurred, if any. 675 * 676 * @returns The number of bytes read. Returns 0 if an error occurred. 677 * 678 * @note The read_some operation may not read all of the requested number of 679 * bytes. Consider using the @ref read function if you need to ensure that the 680 * requested amount of data is read before the blocking operation completes. 681 */ 682 template <typename MutableBufferSequence> read_some(const MutableBufferSequence & buffers,boost::system::error_code & ec)683 std::size_t read_some(const MutableBufferSequence& buffers, 684 boost::system::error_code& ec) 685 { 686 return detail::io(next_layer_, core_, 687 detail::read_op<MutableBufferSequence>(buffers), ec); 688 } 689 690 /// Start an asynchronous read. 691 /** 692 * This function is used to asynchronously read one or more bytes of data from 693 * the stream. The function call always returns immediately. 694 * 695 * @param buffers The buffers into which the data will be read. Although the 696 * buffers object may be copied as necessary, ownership of the underlying 697 * buffers is retained by the caller, which must guarantee that they remain 698 * valid until the handler is called. 699 * 700 * @param handler The handler to be called when the read operation completes. 701 * Copies will be made of the handler as required. The equivalent function 702 * signature of the handler must be: 703 * @code void handler( 704 * const boost::system::error_code& error, // Result of operation. 705 * std::size_t bytes_transferred // Number of bytes read. 706 * ); @endcode 707 * 708 * @note The async_read_some operation may not read all of the requested 709 * number of bytes. Consider using the @ref async_read function if you need to 710 * ensure that the requested amount of data is read before the asynchronous 711 * operation completes. 712 */ 713 template <typename MutableBufferSequence, 714 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, 715 std::size_t)) ReadHandler 716 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))717 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, 718 void (boost::system::error_code, std::size_t)) 719 async_read_some(const MutableBufferSequence& buffers, 720 BOOST_ASIO_MOVE_ARG(ReadHandler) handler 721 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) 722 { 723 return async_initiate<ReadHandler, 724 void (boost::system::error_code, std::size_t)>( 725 initiate_async_read_some(this), handler, buffers); 726 } 727 728 private: 729 class initiate_async_handshake 730 { 731 public: 732 typedef typename stream::executor_type executor_type; 733 initiate_async_handshake(stream * self)734 explicit initiate_async_handshake(stream* self) 735 : self_(self) 736 { 737 } 738 get_executor() const739 executor_type get_executor() const BOOST_ASIO_NOEXCEPT 740 { 741 return self_->get_executor(); 742 } 743 744 template <typename HandshakeHandler> operator ()(BOOST_ASIO_MOVE_ARG (HandshakeHandler)handler,handshake_type type) const745 void operator()(BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler, 746 handshake_type type) const 747 { 748 // If you get an error on the following line it means that your handler 749 // does not meet the documented type requirements for a HandshakeHandler. 750 BOOST_ASIO_HANDSHAKE_HANDLER_CHECK(HandshakeHandler, handler) type_check; 751 752 boost::asio::detail::non_const_lvalue<HandshakeHandler> handler2(handler); 753 detail::async_io(self_->next_layer_, self_->core_, 754 detail::handshake_op(type), handler2.value); 755 } 756 757 private: 758 stream* self_; 759 }; 760 761 class initiate_async_buffered_handshake 762 { 763 public: 764 typedef typename stream::executor_type executor_type; 765 initiate_async_buffered_handshake(stream * self)766 explicit initiate_async_buffered_handshake(stream* self) 767 : self_(self) 768 { 769 } 770 get_executor() const771 executor_type get_executor() const BOOST_ASIO_NOEXCEPT 772 { 773 return self_->get_executor(); 774 } 775 776 template <typename BufferedHandshakeHandler, typename ConstBufferSequence> operator ()(BOOST_ASIO_MOVE_ARG (BufferedHandshakeHandler)handler,handshake_type type,const ConstBufferSequence & buffers) const777 void operator()(BOOST_ASIO_MOVE_ARG(BufferedHandshakeHandler) handler, 778 handshake_type type, const ConstBufferSequence& buffers) const 779 { 780 // If you get an error on the following line it means that your 781 // handler does not meet the documented type requirements for a 782 // BufferedHandshakeHandler. 783 BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( 784 BufferedHandshakeHandler, handler) type_check; 785 786 boost::asio::detail::non_const_lvalue< 787 BufferedHandshakeHandler> handler2(handler); 788 detail::async_io(self_->next_layer_, self_->core_, 789 detail::buffered_handshake_op<ConstBufferSequence>(type, buffers), 790 handler2.value); 791 } 792 793 private: 794 stream* self_; 795 }; 796 797 class initiate_async_shutdown 798 { 799 public: 800 typedef typename stream::executor_type executor_type; 801 initiate_async_shutdown(stream * self)802 explicit initiate_async_shutdown(stream* self) 803 : self_(self) 804 { 805 } 806 get_executor() const807 executor_type get_executor() const BOOST_ASIO_NOEXCEPT 808 { 809 return self_->get_executor(); 810 } 811 812 template <typename ShutdownHandler> operator ()(BOOST_ASIO_MOVE_ARG (ShutdownHandler)handler) const813 void operator()(BOOST_ASIO_MOVE_ARG(ShutdownHandler) handler) const 814 { 815 // If you get an error on the following line it means that your handler 816 // does not meet the documented type requirements for a ShutdownHandler. 817 BOOST_ASIO_HANDSHAKE_HANDLER_CHECK(ShutdownHandler, handler) type_check; 818 819 boost::asio::detail::non_const_lvalue<ShutdownHandler> handler2(handler); 820 detail::async_io(self_->next_layer_, self_->core_, 821 detail::shutdown_op(), handler2.value); 822 } 823 824 private: 825 stream* self_; 826 }; 827 828 class initiate_async_write_some 829 { 830 public: 831 typedef typename stream::executor_type executor_type; 832 initiate_async_write_some(stream * self)833 explicit initiate_async_write_some(stream* self) 834 : self_(self) 835 { 836 } 837 get_executor() const838 executor_type get_executor() const BOOST_ASIO_NOEXCEPT 839 { 840 return self_->get_executor(); 841 } 842 843 template <typename WriteHandler, typename ConstBufferSequence> operator ()(BOOST_ASIO_MOVE_ARG (WriteHandler)handler,const ConstBufferSequence & buffers) const844 void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler, 845 const ConstBufferSequence& buffers) const 846 { 847 // If you get an error on the following line it means that your handler 848 // does not meet the documented type requirements for a WriteHandler. 849 BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; 850 851 boost::asio::detail::non_const_lvalue<WriteHandler> handler2(handler); 852 detail::async_io(self_->next_layer_, self_->core_, 853 detail::write_op<ConstBufferSequence>(buffers), handler2.value); 854 } 855 856 private: 857 stream* self_; 858 }; 859 860 class initiate_async_read_some 861 { 862 public: 863 typedef typename stream::executor_type executor_type; 864 initiate_async_read_some(stream * self)865 explicit initiate_async_read_some(stream* self) 866 : self_(self) 867 { 868 } 869 get_executor() const870 executor_type get_executor() const BOOST_ASIO_NOEXCEPT 871 { 872 return self_->get_executor(); 873 } 874 875 template <typename ReadHandler, typename MutableBufferSequence> operator ()(BOOST_ASIO_MOVE_ARG (ReadHandler)handler,const MutableBufferSequence & buffers) const876 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, 877 const MutableBufferSequence& buffers) const 878 { 879 // If you get an error on the following line it means that your handler 880 // does not meet the documented type requirements for a ReadHandler. 881 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; 882 883 boost::asio::detail::non_const_lvalue<ReadHandler> handler2(handler); 884 detail::async_io(self_->next_layer_, self_->core_, 885 detail::read_op<MutableBufferSequence>(buffers), handler2.value); 886 } 887 888 private: 889 stream* self_; 890 }; 891 892 Stream next_layer_; 893 detail::stream_core core_; 894 }; 895 896 } // namespace ssl 897 } // namespace asio 898 } // namespace boost 899 900 #include <boost/asio/detail/pop_options.hpp> 901 902 #endif // BOOST_ASIO_SSL_STREAM_HPP 903