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