5 // Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11 #ifndef BOOST_ASIO_SSL_STREAM_HPP
12 #define BOOST_ASIO_SSL_STREAM_HPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18 #include <boost/asio/detail/config.hpp>
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/noncopyable.hpp>
24 #include <boost/asio/detail/type_traits.hpp>
25 #include <boost/asio/ssl/context.hpp>
26 #include <boost/asio/ssl/detail/buffered_handshake_op.hpp>
27 #include <boost/asio/ssl/detail/handshake_op.hpp>
28 #include <boost/asio/ssl/detail/io.hpp>
29 #include <boost/asio/ssl/detail/read_op.hpp>
30 #include <boost/asio/ssl/detail/shutdown_op.hpp>
31 #include <boost/asio/ssl/detail/stream_core.hpp>
32 #include <boost/asio/ssl/detail/write_op.hpp>
33 #include <boost/asio/ssl/stream_base.hpp>
35 #include <boost/asio/detail/push_options.hpp>
41 /// Provides stream-oriented functionality using SSL.
43 * The stream class template provides asynchronous and blocking stream-oriented
44 * functionality using SSL.
47 * @e Distinct @e objects: Safe.@n
48 * @e Shared @e objects: Unsafe. The application must also ensure that all
49 * asynchronous operations are performed within the same implicit or explicit
53 * To use the SSL stream template with an ip::tcp::socket, you would write:
55 * boost::asio::io_context io_context;
56 * boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
57 * boost::asio::ssl::stream<asio:ip::tcp::socket> sock(io_context, ctx);
61 * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
63 template <typename Stream>
69 /// The native handle type of the SSL stream.
70 typedef SSL* native_handle_type;
72 /// Structure for use with deprecated impl_type.
78 /// The type of the next layer.
79 typedef typename remove_reference<Stream>::type next_layer_type;
81 /// The type of the lowest layer.
82 typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
84 /// The type of the executor associated with the object.
85 typedef typename lowest_layer_type::executor_type executor_type;
87 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
88 /// Construct a stream.
90 * This constructor creates a stream and initialises the underlying stream
93 * @param arg The argument to be passed to initialise the underlying stream.
95 * @param ctx The SSL context to be used for the stream.
97 template <typename Arg>
98 stream(Arg&& arg, context& ctx)
99 : next_layer_(BOOST_ASIO_MOVE_CAST(Arg)(arg)),
100 core_(ctx.native_handle(),
101 next_layer_.lowest_layer().get_executor().context())
104 #else // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
105 template <typename Arg>
106 stream(Arg& arg, context& ctx)
108 core_(ctx.native_handle(),
109 next_layer_.lowest_layer().get_executor().context())
112 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
116 * @note A @c stream object must not be destroyed while there are pending
117 * asynchronous operations associated with it.
123 /// Get the executor associated with the object.
125 * This function may be used to obtain the executor object that the stream
126 * uses to dispatch handlers for asynchronous operations.
128 * @return A copy of the executor that stream will use to dispatch handlers.
130 executor_type get_executor() BOOST_ASIO_NOEXCEPT
132 return next_layer_.lowest_layer().get_executor();
135 #if !defined(BOOST_ASIO_NO_DEPRECATED)
136 /// (Deprecated: Use get_executor().) Get the io_context associated with the
138 boost::asio::io_context& get_io_context()
140 return next_layer_.lowest_layer().get_io_context();
143 /// (Deprecated: Use get_executor().) Get the io_context associated with the
145 boost::asio::io_context& get_io_service()
147 return next_layer_.lowest_layer().get_io_service();
149 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
151 /// Get the underlying implementation in the native type.
153 * This function may be used to obtain the underlying implementation of the
154 * context. This is intended to allow access to context functionality that is
155 * not otherwise provided.
158 * The native_handle() function returns a pointer of type @c SSL* that is
159 * suitable for passing to functions such as @c SSL_get_verify_result and
160 * @c SSL_get_peer_certificate:
162 * boost::asio::ssl::stream<asio:ip::tcp::socket> sock(io_context, ctx);
164 * // ... establish connection and perform handshake ...
166 * if (X509* cert = SSL_get_peer_certificate(sock.native_handle()))
168 * if (SSL_get_verify_result(sock.native_handle()) == X509_V_OK)
175 native_handle_type native_handle()
177 return core_.engine_.native_handle();
180 /// Get a reference to the next layer.
182 * This function returns a reference to the next layer in a stack of stream
185 * @return A reference to the next layer in the stack of stream layers.
186 * Ownership is not transferred to the caller.
188 const next_layer_type& next_layer() const
193 /// Get a reference to the next layer.
195 * This function returns a reference to the next layer in a stack of stream
198 * @return A reference to the next layer in the stack of stream layers.
199 * Ownership is not transferred to the caller.
201 next_layer_type& next_layer()
206 /// Get a reference to the lowest layer.
208 * This function returns a reference to the lowest layer in a stack of
211 * @return A reference to the lowest layer in the stack of stream layers.
212 * Ownership is not transferred to the caller.
214 lowest_layer_type& lowest_layer()
216 return next_layer_.lowest_layer();
219 /// Get a reference to the lowest layer.
221 * This function returns a reference to the lowest layer in a stack of
224 * @return A reference to the lowest layer in the stack of stream layers.
225 * Ownership is not transferred to the caller.
227 const lowest_layer_type& lowest_layer() const
229 return next_layer_.lowest_layer();
232 /// Set the peer verification mode.
234 * This function may be used to configure the peer verification mode used by
235 * the stream. The new mode will override the mode inherited from the context.
237 * @param v A bitmask of peer verification modes. See @ref verify_mode for
240 * @throws boost::system::system_error Thrown on failure.
242 * @note Calls @c SSL_set_verify.
244 void set_verify_mode(verify_mode v)
246 boost::system::error_code ec;
247 set_verify_mode(v, ec);
248 boost::asio::detail::throw_error(ec, "set_verify_mode");
251 /// Set the peer verification mode.
253 * This function may be used to configure the peer verification mode used by
254 * the stream. The new mode will override the mode inherited from the context.
256 * @param v A bitmask of peer verification modes. See @ref verify_mode for
259 * @param ec Set to indicate what error occurred, if any.
261 * @note Calls @c SSL_set_verify.
263 BOOST_ASIO_SYNC_OP_VOID set_verify_mode(
264 verify_mode v, boost::system::error_code& ec)
266 core_.engine_.set_verify_mode(v, ec);
267 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
270 /// Set the peer verification depth.
272 * This function may be used to configure the maximum verification depth
273 * allowed by the stream.
275 * @param depth Maximum depth for the certificate chain verification that
278 * @throws boost::system::system_error Thrown on failure.
280 * @note Calls @c SSL_set_verify_depth.
282 void set_verify_depth(int depth)
284 boost::system::error_code ec;
285 set_verify_depth(depth, ec);
286 boost::asio::detail::throw_error(ec, "set_verify_depth");
289 /// Set the peer verification depth.
291 * This function may be used to configure the maximum verification depth
292 * allowed by the stream.
294 * @param depth Maximum depth for the certificate chain verification that
297 * @param ec Set to indicate what error occurred, if any.
299 * @note Calls @c SSL_set_verify_depth.
301 BOOST_ASIO_SYNC_OP_VOID set_verify_depth(
302 int depth, boost::system::error_code& ec)
304 core_.engine_.set_verify_depth(depth, ec);
305 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
308 /// Set the callback used to verify peer certificates.
310 * This function is used to specify a callback function that will be called
311 * by the implementation when it needs to verify a peer certificate.
313 * @param callback The function object to be used for verifying a certificate.
314 * The function signature of the handler must be:
315 * @code bool verify_callback(
316 * bool preverified, // True if the certificate passed pre-verification.
317 * verify_context& ctx // The peer certificate and other context.
319 * The return value of the callback is true if the certificate has passed
320 * verification, false otherwise.
322 * @throws boost::system::system_error Thrown on failure.
324 * @note Calls @c SSL_set_verify.
326 template <typename VerifyCallback>
327 void set_verify_callback(VerifyCallback callback)
329 boost::system::error_code ec;
330 this->set_verify_callback(callback, ec);
331 boost::asio::detail::throw_error(ec, "set_verify_callback");
334 /// Set the callback used to verify peer certificates.
336 * This function is used to specify a callback function that will be called
337 * by the implementation when it needs to verify a peer certificate.
339 * @param callback The function object to be used for verifying a certificate.
340 * The function signature of the handler must be:
341 * @code bool verify_callback(
342 * bool preverified, // True if the certificate passed pre-verification.
343 * verify_context& ctx // The peer certificate and other context.
345 * The return value of the callback is true if the certificate has passed
346 * verification, false otherwise.
348 * @param ec Set to indicate what error occurred, if any.
350 * @note Calls @c SSL_set_verify.
352 template <typename VerifyCallback>
353 BOOST_ASIO_SYNC_OP_VOID set_verify_callback(VerifyCallback callback,
354 boost::system::error_code& ec)
356 core_.engine_.set_verify_callback(
357 new detail::verify_callback<VerifyCallback>(callback), ec);
358 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
361 /// Perform SSL handshaking.
363 * This function is used to perform SSL handshaking on the stream. The
364 * function call will block until handshaking is complete or an error occurs.
366 * @param type The type of handshaking to be performed, i.e. as a client or as
369 * @throws boost::system::system_error Thrown on failure.
371 void handshake(handshake_type type)
373 boost::system::error_code ec;
375 boost::asio::detail::throw_error(ec, "handshake");
378 /// Perform SSL handshaking.
380 * This function is used to perform SSL handshaking on the stream. The
381 * function call will block until handshaking is complete or an error occurs.
383 * @param type The type of handshaking to be performed, i.e. as a client or as
386 * @param ec Set to indicate what error occurred, if any.
388 BOOST_ASIO_SYNC_OP_VOID handshake(handshake_type type,
389 boost::system::error_code& ec)
391 detail::io(next_layer_, core_, detail::handshake_op(type), ec);
392 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
395 /// Perform SSL handshaking.
397 * This function is used to perform SSL handshaking on the stream. The
398 * function call will block until handshaking is complete or an error occurs.
400 * @param type The type of handshaking to be performed, i.e. as a client or as
403 * @param buffers The buffered data to be reused for the handshake.
405 * @throws boost::system::system_error Thrown on failure.
407 template <typename ConstBufferSequence>
408 void handshake(handshake_type type, const ConstBufferSequence& buffers)
410 boost::system::error_code ec;
411 handshake(type, buffers, ec);
412 boost::asio::detail::throw_error(ec, "handshake");
415 /// Perform SSL handshaking.
417 * This function is used to perform SSL handshaking on the stream. The
418 * function call will block until handshaking is complete or an error occurs.
420 * @param type The type of handshaking to be performed, i.e. as a client or as
423 * @param buffers The buffered data to be reused for the handshake.
425 * @param ec Set to indicate what error occurred, if any.
427 template <typename ConstBufferSequence>
428 BOOST_ASIO_SYNC_OP_VOID handshake(handshake_type type,
429 const ConstBufferSequence& buffers, boost::system::error_code& ec)
431 detail::io(next_layer_, core_,
432 detail::buffered_handshake_op<ConstBufferSequence>(type, buffers), ec);
433 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
436 /// Start an asynchronous SSL handshake.
438 * This function is used to asynchronously perform an SSL handshake on the
439 * stream. This function call always returns immediately.
441 * @param type The type of handshaking to be performed, i.e. as a client or as
444 * @param handler The handler to be called when the handshake operation
445 * completes. Copies will be made of the handler as required. The equivalent
446 * function signature of the handler must be:
447 * @code void handler(
448 * const boost::system::error_code& error // Result of operation.
451 template <typename HandshakeHandler>
452 BOOST_ASIO_INITFN_RESULT_TYPE(HandshakeHandler,
453 void (boost::system::error_code))
454 async_handshake(handshake_type type,
455 BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler)
457 // If you get an error on the following line it means that your handler does
458 // not meet the documented type requirements for a HandshakeHandler.
459 BOOST_ASIO_HANDSHAKE_HANDLER_CHECK(HandshakeHandler, handler) type_check;
461 boost::asio::async_completion<HandshakeHandler,
462 void (boost::system::error_code)> init(handler);
464 detail::async_io(next_layer_, core_,
465 detail::handshake_op(type), init.completion_handler);
467 return init.result.get();
470 /// Start an asynchronous SSL handshake.
472 * This function is used to asynchronously perform an SSL handshake on the
473 * stream. This function call always returns immediately.
475 * @param type The type of handshaking to be performed, i.e. as a client or as
478 * @param buffers The buffered data to be reused for the handshake. Although
479 * the buffers object may be copied as necessary, ownership of the underlying
480 * buffers is retained by the caller, which must guarantee that they remain
481 * valid until the handler is called.
483 * @param handler The handler to be called when the handshake operation
484 * completes. Copies will be made of the handler as required. The equivalent
485 * function signature of the handler must be:
486 * @code void handler(
487 * const boost::system::error_code& error, // Result of operation.
488 * std::size_t bytes_transferred // Amount of buffers used in handshake.
491 template <typename ConstBufferSequence, typename BufferedHandshakeHandler>
492 BOOST_ASIO_INITFN_RESULT_TYPE(BufferedHandshakeHandler,
493 void (boost::system::error_code, std::size_t))
494 async_handshake(handshake_type type, const ConstBufferSequence& buffers,
495 BOOST_ASIO_MOVE_ARG(BufferedHandshakeHandler) handler)
497 // If you get an error on the following line it means that your handler does
498 // not meet the documented type requirements for a BufferedHandshakeHandler.
499 BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK(
500 BufferedHandshakeHandler, handler) type_check;
502 boost::asio::async_completion<BufferedHandshakeHandler,
503 void (boost::system::error_code, std::size_t)> init(handler);
505 detail::async_io(next_layer_, core_,
506 detail::buffered_handshake_op<ConstBufferSequence>(type, buffers),
507 init.completion_handler);
509 return init.result.get();
512 /// Shut down SSL on the stream.
514 * This function is used to shut down SSL on the stream. The function call
515 * will block until SSL has been shut down or an error occurs.
517 * @throws boost::system::system_error Thrown on failure.
521 boost::system::error_code ec;
523 boost::asio::detail::throw_error(ec, "shutdown");
526 /// Shut down SSL on the stream.
528 * This function is used to shut down SSL on the stream. The function call
529 * will block until SSL has been shut down or an error occurs.
531 * @param ec Set to indicate what error occurred, if any.
533 BOOST_ASIO_SYNC_OP_VOID shutdown(boost::system::error_code& ec)
535 detail::io(next_layer_, core_, detail::shutdown_op(), ec);
536 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
539 /// Asynchronously shut down SSL on the stream.
541 * This function is used to asynchronously shut down SSL on the stream. This
542 * function call always returns immediately.
544 * @param handler The handler to be called when the handshake operation
545 * completes. Copies will be made of the handler as required. The equivalent
546 * function signature of the handler must be:
547 * @code void handler(
548 * const boost::system::error_code& error // Result of operation.
551 template <typename ShutdownHandler>
552 BOOST_ASIO_INITFN_RESULT_TYPE(ShutdownHandler,
553 void (boost::system::error_code))
554 async_shutdown(BOOST_ASIO_MOVE_ARG(ShutdownHandler) handler)
556 // If you get an error on the following line it means that your handler does
557 // not meet the documented type requirements for a ShutdownHandler.
558 BOOST_ASIO_SHUTDOWN_HANDLER_CHECK(ShutdownHandler, handler) type_check;
560 boost::asio::async_completion<ShutdownHandler,
561 void (boost::system::error_code)> init(handler);
563 detail::async_io(next_layer_, core_, detail::shutdown_op(),
564 init.completion_handler);
566 return init.result.get();
569 /// Write some data to the stream.
571 * This function is used to write data on the stream. The function call will
572 * block until one or more bytes of data has been written successfully, or
573 * until an error occurs.
575 * @param buffers The data to be written.
577 * @returns The number of bytes written.
579 * @throws boost::system::system_error Thrown on failure.
581 * @note The write_some operation may not transmit all of the data to the
582 * peer. Consider using the @ref write function if you need to ensure that all
583 * data is written before the blocking operation completes.
585 template <typename ConstBufferSequence>
586 std::size_t write_some(const ConstBufferSequence& buffers)
588 boost::system::error_code ec;
589 std::size_t n = write_some(buffers, ec);
590 boost::asio::detail::throw_error(ec, "write_some");
594 /// Write some data to the stream.
596 * This function is used to write data on the stream. The function call will
597 * block until one or more bytes of data has been written successfully, or
598 * until an error occurs.
600 * @param buffers The data to be written to the stream.
602 * @param ec Set to indicate what error occurred, if any.
604 * @returns The number of bytes written. Returns 0 if an error occurred.
606 * @note The write_some operation may not transmit all of the data to the
607 * peer. Consider using the @ref write function if you need to ensure that all
608 * data is written before the blocking operation completes.
610 template <typename ConstBufferSequence>
611 std::size_t write_some(const ConstBufferSequence& buffers,
612 boost::system::error_code& ec)
614 return detail::io(next_layer_, core_,
615 detail::write_op<ConstBufferSequence>(buffers), ec);
618 /// Start an asynchronous write.
620 * This function is used to asynchronously write one or more bytes of data to
621 * the stream. The function call always returns immediately.
623 * @param buffers The data to be written to the stream. Although the buffers
624 * object may be copied as necessary, ownership of the underlying buffers is
625 * retained by the caller, which must guarantee that they remain valid until
626 * the handler is called.
628 * @param handler The handler to be called when the write operation completes.
629 * Copies will be made of the handler as required. The equivalent function
630 * signature of the handler must be:
631 * @code void handler(
632 * const boost::system::error_code& error, // Result of operation.
633 * std::size_t bytes_transferred // Number of bytes written.
636 * @note The async_write_some operation may not transmit all of the data to
637 * the peer. Consider using the @ref async_write function if you need to
638 * ensure that all data is written before the blocking operation completes.
640 template <typename ConstBufferSequence, typename WriteHandler>
641 BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
642 void (boost::system::error_code, std::size_t))
643 async_write_some(const ConstBufferSequence& buffers,
644 BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
646 // If you get an error on the following line it means that your handler does
647 // not meet the documented type requirements for a WriteHandler.
648 BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
650 boost::asio::async_completion<WriteHandler,
651 void (boost::system::error_code, std::size_t)> init(handler);
653 detail::async_io(next_layer_, core_,
654 detail::write_op<ConstBufferSequence>(buffers),
655 init.completion_handler);
657 return init.result.get();
660 /// Read some data from the stream.
662 * This function is used to read data from the stream. The function call will
663 * block until one or more bytes of data has been read successfully, or until
666 * @param buffers The buffers into which the data will be read.
668 * @returns The number of bytes read.
670 * @throws boost::system::system_error Thrown on failure.
672 * @note The read_some operation may not read all of the requested number of
673 * bytes. Consider using the @ref read function if you need to ensure that the
674 * requested amount of data is read before the blocking operation completes.
676 template <typename MutableBufferSequence>
677 std::size_t read_some(const MutableBufferSequence& buffers)
679 boost::system::error_code ec;
680 std::size_t n = read_some(buffers, ec);
681 boost::asio::detail::throw_error(ec, "read_some");
685 /// Read some data from the stream.
687 * This function is used to read data from the stream. The function call will
688 * block until one or more bytes of data has been read successfully, or until
691 * @param buffers The buffers into which the data will be read.
693 * @param ec Set to indicate what error occurred, if any.
695 * @returns The number of bytes read. Returns 0 if an error occurred.
697 * @note The read_some operation may not read all of the requested number of
698 * bytes. Consider using the @ref read function if you need to ensure that the
699 * requested amount of data is read before the blocking operation completes.
701 template <typename MutableBufferSequence>
702 std::size_t read_some(const MutableBufferSequence& buffers,
703 boost::system::error_code& ec)
705 return detail::io(next_layer_, core_,
706 detail::read_op<MutableBufferSequence>(buffers), ec);
709 /// Start an asynchronous read.
711 * This function is used to asynchronously read one or more bytes of data from
712 * the stream. The function call always returns immediately.
714 * @param buffers The buffers into which the data will be read. Although the
715 * buffers object may be copied as necessary, ownership of the underlying
716 * buffers is retained by the caller, which must guarantee that they remain
717 * valid until the handler is called.
719 * @param handler The handler to be called when the read operation completes.
720 * Copies will be made of the handler as required. The equivalent function
721 * signature of the handler must be:
722 * @code void handler(
723 * const boost::system::error_code& error, // Result of operation.
724 * std::size_t bytes_transferred // Number of bytes read.
727 * @note The async_read_some operation may not read all of the requested
728 * number of bytes. Consider using the @ref async_read function if you need to
729 * ensure that the requested amount of data is read before the asynchronous
730 * operation completes.
732 template <typename MutableBufferSequence, typename ReadHandler>
733 BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
734 void (boost::system::error_code, std::size_t))
735 async_read_some(const MutableBufferSequence& buffers,
736 BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
738 // If you get an error on the following line it means that your handler does
739 // not meet the documented type requirements for a ReadHandler.
740 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
742 boost::asio::async_completion<ReadHandler,
743 void (boost::system::error_code, std::size_t)> init(handler);
745 detail::async_io(next_layer_, core_,
746 detail::read_op<MutableBufferSequence>(buffers),
747 init.completion_handler);
749 return init.result.get();
754 detail::stream_core core_;
761 #include <boost/asio/detail/pop_options.hpp>
763 #endif // BOOST_ASIO_SSL_STREAM_HPP