]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // ssl/stream.hpp | |
3 | // ~~~~~~~~~~~~~~ | |
4 | // | |
92f5a8d4 | 5 | // Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
7c673cae FG |
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 | ||
b32b8144 FG |
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> | |
92f5a8d4 | 23 | #include <boost/asio/detail/non_const_lvalue.hpp> |
b32b8144 FG |
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> | |
7c673cae FG |
35 | |
36 | #include <boost/asio/detail/push_options.hpp> | |
37 | ||
38 | namespace boost { | |
39 | namespace asio { | |
40 | namespace ssl { | |
41 | ||
7c673cae FG |
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 | |
92f5a8d4 | 56 | * boost::asio::io_context my_context; |
7c673cae | 57 | * boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); |
92f5a8d4 | 58 | * boost::asio::ssl::stream<asio:ip::tcp::socket> sock(my_context, ctx); |
7c673cae FG |
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 | ||
7c673cae FG |
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 | ||
b32b8144 FG |
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) | |
7c673cae FG |
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> | |
b32b8144 FG |
99 | stream(Arg&& arg, context& ctx) |
100 | : next_layer_(BOOST_ASIO_MOVE_CAST(Arg)(arg)), | |
92f5a8d4 | 101 | core_(ctx.native_handle(), next_layer_.lowest_layer().get_executor()) |
b32b8144 FG |
102 | { |
103 | } | |
104 | #else // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) | |
105 | template <typename Arg> | |
7c673cae FG |
106 | stream(Arg& arg, context& ctx) |
107 | : next_layer_(arg), | |
92f5a8d4 | 108 | core_(ctx.native_handle(), next_layer_.lowest_layer().get_executor()) |
7c673cae | 109 | { |
7c673cae | 110 | } |
b32b8144 | 111 | #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) |
7c673cae FG |
112 | |
113 | /// Destructor. | |
b32b8144 FG |
114 | /** |
115 | * @note A @c stream object must not be destroyed while there are pending | |
116 | * asynchronous operations associated with it. | |
117 | */ | |
7c673cae FG |
118 | ~stream() |
119 | { | |
120 | } | |
121 | ||
b32b8144 | 122 | /// Get the executor associated with the object. |
7c673cae | 123 | /** |
b32b8144 | 124 | * This function may be used to obtain the executor object that the stream |
7c673cae FG |
125 | * uses to dispatch handlers for asynchronous operations. |
126 | * | |
b32b8144 | 127 | * @return A copy of the executor that stream will use to dispatch handlers. |
7c673cae | 128 | */ |
b32b8144 FG |
129 | executor_type get_executor() BOOST_ASIO_NOEXCEPT |
130 | { | |
131 | return next_layer_.lowest_layer().get_executor(); | |
132 | } | |
133 | ||
7c673cae FG |
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 | |
92f5a8d4 | 145 | * boost::asio::ssl::stream<asio:ip::tcp::socket> sock(my_context, ctx); |
7c673cae FG |
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 | ||
7c673cae FG |
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 | */ | |
b32b8144 | 246 | BOOST_ASIO_SYNC_OP_VOID set_verify_mode( |
7c673cae FG |
247 | verify_mode v, boost::system::error_code& ec) |
248 | { | |
b32b8144 FG |
249 | core_.engine_.set_verify_mode(v, ec); |
250 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); | |
7c673cae FG |
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 | */ | |
b32b8144 | 284 | BOOST_ASIO_SYNC_OP_VOID set_verify_depth( |
7c673cae FG |
285 | int depth, boost::system::error_code& ec) |
286 | { | |
b32b8144 FG |
287 | core_.engine_.set_verify_depth(depth, ec); |
288 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); | |
7c673cae FG |
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> | |
b32b8144 | 336 | BOOST_ASIO_SYNC_OP_VOID set_verify_callback(VerifyCallback callback, |
7c673cae FG |
337 | boost::system::error_code& ec) |
338 | { | |
b32b8144 | 339 | core_.engine_.set_verify_callback( |
7c673cae | 340 | new detail::verify_callback<VerifyCallback>(callback), ec); |
b32b8144 | 341 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
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 | */ | |
b32b8144 | 371 | BOOST_ASIO_SYNC_OP_VOID handshake(handshake_type type, |
7c673cae FG |
372 | boost::system::error_code& ec) |
373 | { | |
374 | detail::io(next_layer_, core_, detail::handshake_op(type), ec); | |
b32b8144 | 375 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
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> | |
b32b8144 | 411 | BOOST_ASIO_SYNC_OP_VOID handshake(handshake_type type, |
7c673cae FG |
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); | |
b32b8144 | 416 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
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 | */ | |
92f5a8d4 TL |
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, | |
7c673cae FG |
439 | void (boost::system::error_code)) |
440 | async_handshake(handshake_type type, | |
92f5a8d4 TL |
441 | BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler |
442 | BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) | |
7c673cae | 443 | { |
92f5a8d4 TL |
444 | return async_initiate<HandshakeHandler, |
445 | void (boost::system::error_code)>( | |
446 | initiate_async_handshake(this), handler, type); | |
7c673cae FG |
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 | */ | |
92f5a8d4 TL |
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, | |
7c673cae FG |
475 | void (boost::system::error_code, std::size_t)) |
476 | async_handshake(handshake_type type, const ConstBufferSequence& buffers, | |
92f5a8d4 TL |
477 | BOOST_ASIO_MOVE_ARG(BufferedHandshakeHandler) handler |
478 | BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) | |
7c673cae | 479 | { |
92f5a8d4 TL |
480 | return async_initiate<BufferedHandshakeHandler, |
481 | void (boost::system::error_code, std::size_t)>( | |
482 | initiate_async_buffered_handshake(this), handler, type, buffers); | |
7c673cae FG |
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 | */ | |
b32b8144 | 506 | BOOST_ASIO_SYNC_OP_VOID shutdown(boost::system::error_code& ec) |
7c673cae FG |
507 | { |
508 | detail::io(next_layer_, core_, detail::shutdown_op(), ec); | |
b32b8144 | 509 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
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 | */ | |
92f5a8d4 TL |
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, | |
7c673cae | 529 | void (boost::system::error_code)) |
92f5a8d4 TL |
530 | async_shutdown( |
531 | BOOST_ASIO_MOVE_ARG(ShutdownHandler) handler | |
532 | BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) | |
7c673cae | 533 | { |
92f5a8d4 TL |
534 | return async_initiate<ShutdownHandler, |
535 | void (boost::system::error_code)>( | |
536 | initiate_async_shutdown(this), handler); | |
7c673cae FG |
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 | |
92f5a8d4 TL |
608 | * ensure that all data is written before the asynchronous operation |
609 | * completes. | |
7c673cae | 610 | */ |
92f5a8d4 TL |
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, | |
7c673cae FG |
616 | void (boost::system::error_code, std::size_t)) |
617 | async_write_some(const ConstBufferSequence& buffers, | |
92f5a8d4 TL |
618 | BOOST_ASIO_MOVE_ARG(WriteHandler) handler |
619 | BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) | |
7c673cae | 620 | { |
92f5a8d4 TL |
621 | return async_initiate<WriteHandler, |
622 | void (boost::system::error_code, std::size_t)>( | |
623 | initiate_async_write_some(this), handler, buffers); | |
7c673cae FG |
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 | */ | |
92f5a8d4 TL |
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, | |
7c673cae FG |
703 | void (boost::system::error_code, std::size_t)) |
704 | async_read_some(const MutableBufferSequence& buffers, | |
92f5a8d4 TL |
705 | BOOST_ASIO_MOVE_ARG(ReadHandler) handler |
706 | BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) | |
7c673cae | 707 | { |
92f5a8d4 TL |
708 | return async_initiate<ReadHandler, |
709 | void (boost::system::error_code, std::size_t)>( | |
710 | initiate_async_read_some(this), handler, buffers); | |
711 | } | |
7c673cae | 712 | |
92f5a8d4 TL |
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 | }; | |
7c673cae | 745 | |
92f5a8d4 TL |
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 | }; | |
7c673cae | 781 | |
92f5a8d4 TL |
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 | }; | |
7c673cae | 876 | |
7c673cae FG |
877 | Stream next_layer_; |
878 | detail::stream_core core_; | |
7c673cae FG |
879 | }; |
880 | ||
7c673cae FG |
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 |