]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/asio/ssl/stream.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / asio / ssl / stream.hpp
1 //
2 // ssl/stream.hpp
3 // ~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2020 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 #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 */
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 */
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 */
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 */
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 */
186 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 */
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 */
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 */
225 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 */
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 */
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 */
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 */
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>
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>
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 */
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 */
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>
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>
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)>
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)>
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 */
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 */
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)>
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>
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>
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)>
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>
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>
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)>
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
734 explicit initiate_async_handshake(stream* self)
735 : self_(self)
736 {
737 }
738
739 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
740 {
741 return self_->get_executor();
742 }
743
744 template <typename HandshakeHandler>
745 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
766 explicit initiate_async_buffered_handshake(stream* self)
767 : self_(self)
768 {
769 }
770
771 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
772 {
773 return self_->get_executor();
774 }
775
776 template <typename BufferedHandshakeHandler, typename ConstBufferSequence>
777 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
802 explicit initiate_async_shutdown(stream* self)
803 : self_(self)
804 {
805 }
806
807 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
808 {
809 return self_->get_executor();
810 }
811
812 template <typename ShutdownHandler>
813 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
833 explicit initiate_async_write_some(stream* self)
834 : self_(self)
835 {
836 }
837
838 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
839 {
840 return self_->get_executor();
841 }
842
843 template <typename WriteHandler, typename ConstBufferSequence>
844 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
865 explicit initiate_async_read_some(stream* self)
866 : self_(self)
867 {
868 }
869
870 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
871 {
872 return self_->get_executor();
873 }
874
875 template <typename ReadHandler, typename MutableBufferSequence>
876 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