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