1 //
2 // basic_socket.hpp
3 // ~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2021 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_BASIC_SOCKET_HPP
12 #define BOOST_ASIO_BASIC_SOCKET_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/any_io_executor.hpp>
19 #include <boost/asio/detail/config.hpp>
20 #include <boost/asio/async_result.hpp>
21 #include <boost/asio/detail/handler_type_requirements.hpp>
22 #include <boost/asio/detail/io_object_impl.hpp>
23 #include <boost/asio/detail/non_const_lvalue.hpp>
24 #include <boost/asio/detail/throw_error.hpp>
25 #include <boost/asio/detail/type_traits.hpp>
26 #include <boost/asio/error.hpp>
27 #include <boost/asio/execution_context.hpp>
28 #include <boost/asio/post.hpp>
29 #include <boost/asio/socket_base.hpp>
30 
31 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
32 # include <boost/asio/detail/null_socket_service.hpp>
33 #elif defined(BOOST_ASIO_HAS_IOCP)
34 # include <boost/asio/detail/win_iocp_socket_service.hpp>
35 #else
36 # include <boost/asio/detail/reactive_socket_service.hpp>
37 #endif
38 
39 #if defined(BOOST_ASIO_HAS_MOVE)
40 # include <utility>
41 #endif // defined(BOOST_ASIO_HAS_MOVE)
42 
43 #include <boost/asio/detail/push_options.hpp>
44 
45 namespace boost {
46 namespace asio {
47 
48 #if !defined(BOOST_ASIO_BASIC_SOCKET_FWD_DECL)
49 #define BOOST_ASIO_BASIC_SOCKET_FWD_DECL
50 
51 // Forward declaration with defaulted arguments.
52 template <typename Protocol, typename Executor = any_io_executor>
53 class basic_socket;
54 
55 #endif // !defined(BOOST_ASIO_BASIC_SOCKET_FWD_DECL)
56 
57 /// Provides socket functionality.
58 /**
59  * The basic_socket class template provides functionality that is common to both
60  * stream-oriented and datagram-oriented sockets.
61  *
62  * @par Thread Safety
63  * @e Distinct @e objects: Safe.@n
64  * @e Shared @e objects: Unsafe.
65  */
66 template <typename Protocol, typename Executor>
67 class basic_socket
68   : public socket_base
69 {
70 public:
71   /// The type of the executor associated with the object.
72   typedef Executor executor_type;
73 
74   /// Rebinds the socket type to another executor.
75   template <typename Executor1>
76   struct rebind_executor
77   {
78     /// The socket type when rebound to the specified executor.
79     typedef basic_socket<Protocol, Executor1> other;
80   };
81 
82   /// The native representation of a socket.
83 #if defined(GENERATING_DOCUMENTATION)
84   typedef implementation_defined native_handle_type;
85 #elif defined(BOOST_ASIO_WINDOWS_RUNTIME)
86   typedef typename detail::null_socket_service<
87     Protocol>::native_handle_type native_handle_type;
88 #elif defined(BOOST_ASIO_HAS_IOCP)
89   typedef typename detail::win_iocp_socket_service<
90     Protocol>::native_handle_type native_handle_type;
91 #else
92   typedef typename detail::reactive_socket_service<
93     Protocol>::native_handle_type native_handle_type;
94 #endif
95 
96   /// The protocol type.
97   typedef Protocol protocol_type;
98 
99   /// The endpoint type.
100   typedef typename Protocol::endpoint endpoint_type;
101 
102 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
103   /// A basic_socket is always the lowest layer.
104   typedef basic_socket<Protocol, Executor> lowest_layer_type;
105 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
106 
107   /// Construct a basic_socket without opening it.
108   /**
109    * This constructor creates a socket without opening it.
110    *
111    * @param ex The I/O executor that the socket will use, by default, to
112    * dispatch handlers for any asynchronous operations performed on the socket.
113    */
basic_socket(const executor_type & ex)114   explicit basic_socket(const executor_type& ex)
115     : impl_(0, ex)
116   {
117   }
118 
119   /// Construct a basic_socket without opening it.
120   /**
121    * This constructor creates a socket without opening it.
122    *
123    * @param context An execution context which provides the I/O executor that
124    * the socket will use, by default, to dispatch handlers for any asynchronous
125    * operations performed on the socket.
126    */
127   template <typename ExecutionContext>
basic_socket(ExecutionContext & context,typename constraint<is_convertible<ExecutionContext &,execution_context &>::value>::type=0)128   explicit basic_socket(ExecutionContext& context,
129       typename constraint<
130         is_convertible<ExecutionContext&, execution_context&>::value
131       >::type = 0)
132     : impl_(0, 0, context)
133   {
134   }
135 
136   /// Construct and open a basic_socket.
137   /**
138    * This constructor creates and opens a socket.
139    *
140    * @param ex The I/O executor that the socket will use, by default, to
141    * dispatch handlers for any asynchronous operations performed on the socket.
142    *
143    * @param protocol An object specifying protocol parameters to be used.
144    *
145    * @throws boost::system::system_error Thrown on failure.
146    */
basic_socket(const executor_type & ex,const protocol_type & protocol)147   basic_socket(const executor_type& ex, const protocol_type& protocol)
148     : impl_(0, ex)
149   {
150     boost::system::error_code ec;
151     impl_.get_service().open(impl_.get_implementation(), protocol, ec);
152     boost::asio::detail::throw_error(ec, "open");
153   }
154 
155   /// Construct and open a basic_socket.
156   /**
157    * This constructor creates and opens a socket.
158    *
159    * @param context An execution context which provides the I/O executor that
160    * the socket will use, by default, to dispatch handlers for any asynchronous
161    * operations performed on the socket.
162    *
163    * @param protocol An object specifying protocol parameters to be used.
164    *
165    * @throws boost::system::system_error Thrown on failure.
166    */
167   template <typename ExecutionContext>
basic_socket(ExecutionContext & context,const protocol_type & protocol,typename constraint<is_convertible<ExecutionContext &,execution_context &>::value,defaulted_constraint>::type=defaulted_constraint ())168   basic_socket(ExecutionContext& context, const protocol_type& protocol,
169       typename constraint<
170         is_convertible<ExecutionContext&, execution_context&>::value,
171         defaulted_constraint
172       >::type = defaulted_constraint())
173     : impl_(0, 0, context)
174   {
175     boost::system::error_code ec;
176     impl_.get_service().open(impl_.get_implementation(), protocol, ec);
177     boost::asio::detail::throw_error(ec, "open");
178   }
179 
180   /// Construct a basic_socket, opening it and binding it to the given local
181   /// endpoint.
182   /**
183    * This constructor creates a socket and automatically opens it bound to the
184    * specified endpoint on the local machine. The protocol used is the protocol
185    * associated with the given endpoint.
186    *
187    * @param ex The I/O executor that the socket will use, by default, to
188    * dispatch handlers for any asynchronous operations performed on the socket.
189    *
190    * @param endpoint An endpoint on the local machine to which the socket will
191    * be bound.
192    *
193    * @throws boost::system::system_error Thrown on failure.
194    */
basic_socket(const executor_type & ex,const endpoint_type & endpoint)195   basic_socket(const executor_type& ex, const endpoint_type& endpoint)
196     : impl_(0, ex)
197   {
198     boost::system::error_code ec;
199     const protocol_type protocol = endpoint.protocol();
200     impl_.get_service().open(impl_.get_implementation(), protocol, ec);
201     boost::asio::detail::throw_error(ec, "open");
202     impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);
203     boost::asio::detail::throw_error(ec, "bind");
204   }
205 
206   /// Construct a basic_socket, opening it and binding it to the given local
207   /// endpoint.
208   /**
209    * This constructor creates a socket and automatically opens it bound to the
210    * specified endpoint on the local machine. The protocol used is the protocol
211    * associated with the given endpoint.
212    *
213    * @param context An execution context which provides the I/O executor that
214    * the socket will use, by default, to dispatch handlers for any asynchronous
215    * operations performed on the socket.
216    *
217    * @param endpoint An endpoint on the local machine to which the socket will
218    * be bound.
219    *
220    * @throws boost::system::system_error Thrown on failure.
221    */
222   template <typename ExecutionContext>
basic_socket(ExecutionContext & context,const endpoint_type & endpoint,typename constraint<is_convertible<ExecutionContext &,execution_context &>::value>::type=0)223   basic_socket(ExecutionContext& context, const endpoint_type& endpoint,
224       typename constraint<
225         is_convertible<ExecutionContext&, execution_context&>::value
226       >::type = 0)
227     : impl_(0, 0, context)
228   {
229     boost::system::error_code ec;
230     const protocol_type protocol = endpoint.protocol();
231     impl_.get_service().open(impl_.get_implementation(), protocol, ec);
232     boost::asio::detail::throw_error(ec, "open");
233     impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);
234     boost::asio::detail::throw_error(ec, "bind");
235   }
236 
237   /// Construct a basic_socket on an existing native socket.
238   /**
239    * This constructor creates a socket object to hold an existing native socket.
240    *
241    * @param ex The I/O executor that the socket will use, by default, to
242    * dispatch handlers for any asynchronous operations performed on the socket.
243    *
244    * @param protocol An object specifying protocol parameters to be used.
245    *
246    * @param native_socket A native socket.
247    *
248    * @throws boost::system::system_error Thrown on failure.
249    */
basic_socket(const executor_type & ex,const protocol_type & protocol,const native_handle_type & native_socket)250   basic_socket(const executor_type& ex, const protocol_type& protocol,
251       const native_handle_type& native_socket)
252     : impl_(0, ex)
253   {
254     boost::system::error_code ec;
255     impl_.get_service().assign(impl_.get_implementation(),
256         protocol, native_socket, ec);
257     boost::asio::detail::throw_error(ec, "assign");
258   }
259 
260   /// Construct a basic_socket on an existing native socket.
261   /**
262    * This constructor creates a socket object to hold an existing native socket.
263    *
264    * @param context An execution context which provides the I/O executor that
265    * the socket will use, by default, to dispatch handlers for any asynchronous
266    * operations performed on the socket.
267    *
268    * @param protocol An object specifying protocol parameters to be used.
269    *
270    * @param native_socket A native socket.
271    *
272    * @throws boost::system::system_error Thrown on failure.
273    */
274   template <typename ExecutionContext>
basic_socket(ExecutionContext & context,const protocol_type & protocol,const native_handle_type & native_socket,typename constraint<is_convertible<ExecutionContext &,execution_context &>::value>::type=0)275   basic_socket(ExecutionContext& context, const protocol_type& protocol,
276       const native_handle_type& native_socket,
277       typename constraint<
278         is_convertible<ExecutionContext&, execution_context&>::value
279       >::type = 0)
280     : impl_(0, 0, context)
281   {
282     boost::system::error_code ec;
283     impl_.get_service().assign(impl_.get_implementation(),
284         protocol, native_socket, ec);
285     boost::asio::detail::throw_error(ec, "assign");
286   }
287 
288 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
289   /// Move-construct a basic_socket from another.
290   /**
291    * This constructor moves a socket from one object to another.
292    *
293    * @param other The other basic_socket object from which the move will
294    * occur.
295    *
296    * @note Following the move, the moved-from object is in the same state as if
297    * constructed using the @c basic_socket(const executor_type&) constructor.
298    */
basic_socket(basic_socket && other)299   basic_socket(basic_socket&& other) BOOST_ASIO_NOEXCEPT
300     : impl_(std::move(other.impl_))
301   {
302   }
303 
304   /// Move-assign a basic_socket from another.
305   /**
306    * This assignment operator moves a socket from one object to another.
307    *
308    * @param other The other basic_socket object from which the move will
309    * occur.
310    *
311    * @note Following the move, the moved-from object is in the same state as if
312    * constructed using the @c basic_socket(const executor_type&) constructor.
313    */
operator =(basic_socket && other)314   basic_socket& operator=(basic_socket&& other)
315   {
316     impl_ = std::move(other.impl_);
317     return *this;
318   }
319 
320   // All sockets have access to each other's implementations.
321   template <typename Protocol1, typename Executor1>
322   friend class basic_socket;
323 
324   /// Move-construct a basic_socket from a socket of another protocol type.
325   /**
326    * This constructor moves a socket from one object to another.
327    *
328    * @param other The other basic_socket object from which the move will
329    * occur.
330    *
331    * @note Following the move, the moved-from object is in the same state as if
332    * constructed using the @c basic_socket(const executor_type&) constructor.
333    */
334   template <typename Protocol1, typename Executor1>
basic_socket(basic_socket<Protocol1,Executor1> && other,typename constraint<is_convertible<Protocol1,Protocol>::value && is_convertible<Executor1,Executor>::value>::type=0)335   basic_socket(basic_socket<Protocol1, Executor1>&& other,
336       typename constraint<
337         is_convertible<Protocol1, Protocol>::value
338           && is_convertible<Executor1, Executor>::value
339       >::type = 0)
340     : impl_(std::move(other.impl_))
341   {
342   }
343 
344   /// Move-assign a basic_socket from a socket of another protocol type.
345   /**
346    * This assignment operator moves a socket from one object to another.
347    *
348    * @param other The other basic_socket object from which the move will
349    * occur.
350    *
351    * @note Following the move, the moved-from object is in the same state as if
352    * constructed using the @c basic_socket(const executor_type&) constructor.
353    */
354   template <typename Protocol1, typename Executor1>
355   typename constraint<
356     is_convertible<Protocol1, Protocol>::value
357       && is_convertible<Executor1, Executor>::value,
358     basic_socket&
operator =(basic_socket<Protocol1,Executor1> && other)359   >::type operator=(basic_socket<Protocol1, Executor1> && other)
360   {
361     basic_socket tmp(std::move(other));
362     impl_ = std::move(tmp.impl_);
363     return *this;
364   }
365 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
366 
367   /// Get the executor associated with the object.
get_executor()368   executor_type get_executor() BOOST_ASIO_NOEXCEPT
369   {
370     return impl_.get_executor();
371   }
372 
373 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
374   /// Get a reference to the lowest layer.
375   /**
376    * This function returns a reference to the lowest layer in a stack of
377    * layers. Since a basic_socket cannot contain any further layers, it simply
378    * returns a reference to itself.
379    *
380    * @return A reference to the lowest layer in the stack of layers. Ownership
381    * is not transferred to the caller.
382    */
lowest_layer()383   lowest_layer_type& lowest_layer()
384   {
385     return *this;
386   }
387 
388   /// Get a const reference to the lowest layer.
389   /**
390    * This function returns a const reference to the lowest layer in a stack of
391    * layers. Since a basic_socket cannot contain any further layers, it simply
392    * returns a reference to itself.
393    *
394    * @return A const reference to the lowest layer in the stack of layers.
395    * Ownership is not transferred to the caller.
396    */
lowest_layer() const397   const lowest_layer_type& lowest_layer() const
398   {
399     return *this;
400   }
401 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
402 
403   /// Open the socket using the specified protocol.
404   /**
405    * This function opens the socket so that it will use the specified protocol.
406    *
407    * @param protocol An object specifying protocol parameters to be used.
408    *
409    * @throws boost::system::system_error Thrown on failure.
410    *
411    * @par Example
412    * @code
413    * boost::asio::ip::tcp::socket socket(my_context);
414    * socket.open(boost::asio::ip::tcp::v4());
415    * @endcode
416    */
open(const protocol_type & protocol=protocol_type ())417   void open(const protocol_type& protocol = protocol_type())
418   {
419     boost::system::error_code ec;
420     impl_.get_service().open(impl_.get_implementation(), protocol, ec);
421     boost::asio::detail::throw_error(ec, "open");
422   }
423 
424   /// Open the socket using the specified protocol.
425   /**
426    * This function opens the socket so that it will use the specified protocol.
427    *
428    * @param protocol An object specifying which protocol is to be used.
429    *
430    * @param ec Set to indicate what error occurred, if any.
431    *
432    * @par Example
433    * @code
434    * boost::asio::ip::tcp::socket socket(my_context);
435    * boost::system::error_code ec;
436    * socket.open(boost::asio::ip::tcp::v4(), ec);
437    * if (ec)
438    * {
439    *   // An error occurred.
440    * }
441    * @endcode
442    */
open(const protocol_type & protocol,boost::system::error_code & ec)443   BOOST_ASIO_SYNC_OP_VOID open(const protocol_type& protocol,
444       boost::system::error_code& ec)
445   {
446     impl_.get_service().open(impl_.get_implementation(), protocol, ec);
447     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
448   }
449 
450   /// Assign an existing native socket to the socket.
451   /*
452    * This function opens the socket to hold an existing native socket.
453    *
454    * @param protocol An object specifying which protocol is to be used.
455    *
456    * @param native_socket A native socket.
457    *
458    * @throws boost::system::system_error Thrown on failure.
459    */
assign(const protocol_type & protocol,const native_handle_type & native_socket)460   void assign(const protocol_type& protocol,
461       const native_handle_type& native_socket)
462   {
463     boost::system::error_code ec;
464     impl_.get_service().assign(impl_.get_implementation(),
465         protocol, native_socket, ec);
466     boost::asio::detail::throw_error(ec, "assign");
467   }
468 
469   /// Assign an existing native socket to the socket.
470   /*
471    * This function opens the socket to hold an existing native socket.
472    *
473    * @param protocol An object specifying which protocol is to be used.
474    *
475    * @param native_socket A native socket.
476    *
477    * @param ec Set to indicate what error occurred, if any.
478    */
assign(const protocol_type & protocol,const native_handle_type & native_socket,boost::system::error_code & ec)479   BOOST_ASIO_SYNC_OP_VOID assign(const protocol_type& protocol,
480       const native_handle_type& native_socket, boost::system::error_code& ec)
481   {
482     impl_.get_service().assign(impl_.get_implementation(),
483         protocol, native_socket, ec);
484     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
485   }
486 
487   /// Determine whether the socket is open.
is_open() const488   bool is_open() const
489   {
490     return impl_.get_service().is_open(impl_.get_implementation());
491   }
492 
493   /// Close the socket.
494   /**
495    * This function is used to close the socket. Any asynchronous send, receive
496    * or connect operations will be cancelled immediately, and will complete
497    * with the boost::asio::error::operation_aborted error.
498    *
499    * @throws boost::system::system_error Thrown on failure. Note that, even if
500    * the function indicates an error, the underlying descriptor is closed.
501    *
502    * @note For portable behaviour with respect to graceful closure of a
503    * connected socket, call shutdown() before closing the socket.
504    */
close()505   void close()
506   {
507     boost::system::error_code ec;
508     impl_.get_service().close(impl_.get_implementation(), ec);
509     boost::asio::detail::throw_error(ec, "close");
510   }
511 
512   /// Close the socket.
513   /**
514    * This function is used to close the socket. Any asynchronous send, receive
515    * or connect operations will be cancelled immediately, and will complete
516    * with the boost::asio::error::operation_aborted error.
517    *
518    * @param ec Set to indicate what error occurred, if any. Note that, even if
519    * the function indicates an error, the underlying descriptor is closed.
520    *
521    * @par Example
522    * @code
523    * boost::asio::ip::tcp::socket socket(my_context);
524    * ...
525    * boost::system::error_code ec;
526    * socket.close(ec);
527    * if (ec)
528    * {
529    *   // An error occurred.
530    * }
531    * @endcode
532    *
533    * @note For portable behaviour with respect to graceful closure of a
534    * connected socket, call shutdown() before closing the socket.
535    */
close(boost::system::error_code & ec)536   BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
537   {
538     impl_.get_service().close(impl_.get_implementation(), ec);
539     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
540   }
541 
542   /// Release ownership of the underlying native socket.
543   /**
544    * This function causes all outstanding asynchronous connect, send and receive
545    * operations to finish immediately, and the handlers for cancelled operations
546    * will be passed the boost::asio::error::operation_aborted error. Ownership
547    * of the native socket is then transferred to the caller.
548    *
549    * @throws boost::system::system_error Thrown on failure.
550    *
551    * @note This function is unsupported on Windows versions prior to Windows
552    * 8.1, and will fail with boost::asio::error::operation_not_supported on
553    * these platforms.
554    */
555 #if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
556   && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)
557   __declspec(deprecated("This function always fails with "
558         "operation_not_supported when used on Windows versions "
559         "prior to Windows 8.1."))
560 #endif
release()561   native_handle_type release()
562   {
563     boost::system::error_code ec;
564     native_handle_type s = impl_.get_service().release(
565         impl_.get_implementation(), ec);
566     boost::asio::detail::throw_error(ec, "release");
567     return s;
568   }
569 
570   /// Release ownership of the underlying native socket.
571   /**
572    * This function causes all outstanding asynchronous connect, send and receive
573    * operations to finish immediately, and the handlers for cancelled operations
574    * will be passed the boost::asio::error::operation_aborted error. Ownership
575    * of the native socket is then transferred to the caller.
576    *
577    * @param ec Set to indicate what error occurred, if any.
578    *
579    * @note This function is unsupported on Windows versions prior to Windows
580    * 8.1, and will fail with boost::asio::error::operation_not_supported on
581    * these platforms.
582    */
583 #if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
584   && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)
585   __declspec(deprecated("This function always fails with "
586         "operation_not_supported when used on Windows versions "
587         "prior to Windows 8.1."))
588 #endif
release(boost::system::error_code & ec)589   native_handle_type release(boost::system::error_code& ec)
590   {
591     return impl_.get_service().release(impl_.get_implementation(), ec);
592   }
593 
594   /// Get the native socket representation.
595   /**
596    * This function may be used to obtain the underlying representation of the
597    * socket. This is intended to allow access to native socket functionality
598    * that is not otherwise provided.
599    */
native_handle()600   native_handle_type native_handle()
601   {
602     return impl_.get_service().native_handle(impl_.get_implementation());
603   }
604 
605   /// Cancel all asynchronous operations associated with the socket.
606   /**
607    * This function causes all outstanding asynchronous connect, send and receive
608    * operations to finish immediately, and the handlers for cancelled operations
609    * will be passed the boost::asio::error::operation_aborted error.
610    *
611    * @throws boost::system::system_error Thrown on failure.
612    *
613    * @note Calls to cancel() will always fail with
614    * boost::asio::error::operation_not_supported when run on Windows XP, Windows
615    * Server 2003, and earlier versions of Windows, unless
616    * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has
617    * two issues that should be considered before enabling its use:
618    *
619    * @li It will only cancel asynchronous operations that were initiated in the
620    * current thread.
621    *
622    * @li It can appear to complete without error, but the request to cancel the
623    * unfinished operations may be silently ignored by the operating system.
624    * Whether it works or not seems to depend on the drivers that are installed.
625    *
626    * For portable cancellation, consider using one of the following
627    * alternatives:
628    *
629    * @li Disable asio's I/O completion port backend by defining
630    * BOOST_ASIO_DISABLE_IOCP.
631    *
632    * @li Use the close() function to simultaneously cancel the outstanding
633    * operations and close the socket.
634    *
635    * When running on Windows Vista, Windows Server 2008, and later, the
636    * CancelIoEx function is always used. This function does not have the
637    * problems described above.
638    */
639 #if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
640   && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \
641   && !defined(BOOST_ASIO_ENABLE_CANCELIO)
642   __declspec(deprecated("By default, this function always fails with "
643         "operation_not_supported when used on Windows XP, Windows Server 2003, "
644         "or earlier. Consult documentation for details."))
645 #endif
cancel()646   void cancel()
647   {
648     boost::system::error_code ec;
649     impl_.get_service().cancel(impl_.get_implementation(), ec);
650     boost::asio::detail::throw_error(ec, "cancel");
651   }
652 
653   /// Cancel all asynchronous operations associated with the socket.
654   /**
655    * This function causes all outstanding asynchronous connect, send and receive
656    * operations to finish immediately, and the handlers for cancelled operations
657    * will be passed the boost::asio::error::operation_aborted error.
658    *
659    * @param ec Set to indicate what error occurred, if any.
660    *
661    * @note Calls to cancel() will always fail with
662    * boost::asio::error::operation_not_supported when run on Windows XP, Windows
663    * Server 2003, and earlier versions of Windows, unless
664    * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has
665    * two issues that should be considered before enabling its use:
666    *
667    * @li It will only cancel asynchronous operations that were initiated in the
668    * current thread.
669    *
670    * @li It can appear to complete without error, but the request to cancel the
671    * unfinished operations may be silently ignored by the operating system.
672    * Whether it works or not seems to depend on the drivers that are installed.
673    *
674    * For portable cancellation, consider using one of the following
675    * alternatives:
676    *
677    * @li Disable asio's I/O completion port backend by defining
678    * BOOST_ASIO_DISABLE_IOCP.
679    *
680    * @li Use the close() function to simultaneously cancel the outstanding
681    * operations and close the socket.
682    *
683    * When running on Windows Vista, Windows Server 2008, and later, the
684    * CancelIoEx function is always used. This function does not have the
685    * problems described above.
686    */
687 #if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
688   && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \
689   && !defined(BOOST_ASIO_ENABLE_CANCELIO)
690   __declspec(deprecated("By default, this function always fails with "
691         "operation_not_supported when used on Windows XP, Windows Server 2003, "
692         "or earlier. Consult documentation for details."))
693 #endif
cancel(boost::system::error_code & ec)694   BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
695   {
696     impl_.get_service().cancel(impl_.get_implementation(), ec);
697     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
698   }
699 
700   /// Determine whether the socket is at the out-of-band data mark.
701   /**
702    * This function is used to check whether the socket input is currently
703    * positioned at the out-of-band data mark.
704    *
705    * @return A bool indicating whether the socket is at the out-of-band data
706    * mark.
707    *
708    * @throws boost::system::system_error Thrown on failure.
709    */
at_mark() const710   bool at_mark() const
711   {
712     boost::system::error_code ec;
713     bool b = impl_.get_service().at_mark(impl_.get_implementation(), ec);
714     boost::asio::detail::throw_error(ec, "at_mark");
715     return b;
716   }
717 
718   /// Determine whether the socket is at the out-of-band data mark.
719   /**
720    * This function is used to check whether the socket input is currently
721    * positioned at the out-of-band data mark.
722    *
723    * @param ec Set to indicate what error occurred, if any.
724    *
725    * @return A bool indicating whether the socket is at the out-of-band data
726    * mark.
727    */
at_mark(boost::system::error_code & ec) const728   bool at_mark(boost::system::error_code& ec) const
729   {
730     return impl_.get_service().at_mark(impl_.get_implementation(), ec);
731   }
732 
733   /// Determine the number of bytes available for reading.
734   /**
735    * This function is used to determine the number of bytes that may be read
736    * without blocking.
737    *
738    * @return The number of bytes that may be read without blocking, or 0 if an
739    * error occurs.
740    *
741    * @throws boost::system::system_error Thrown on failure.
742    */
available() const743   std::size_t available() const
744   {
745     boost::system::error_code ec;
746     std::size_t s = impl_.get_service().available(
747         impl_.get_implementation(), ec);
748     boost::asio::detail::throw_error(ec, "available");
749     return s;
750   }
751 
752   /// Determine the number of bytes available for reading.
753   /**
754    * This function is used to determine the number of bytes that may be read
755    * without blocking.
756    *
757    * @param ec Set to indicate what error occurred, if any.
758    *
759    * @return The number of bytes that may be read without blocking, or 0 if an
760    * error occurs.
761    */
available(boost::system::error_code & ec) const762   std::size_t available(boost::system::error_code& ec) const
763   {
764     return impl_.get_service().available(impl_.get_implementation(), ec);
765   }
766 
767   /// Bind the socket to the given local endpoint.
768   /**
769    * This function binds the socket to the specified endpoint on the local
770    * machine.
771    *
772    * @param endpoint An endpoint on the local machine to which the socket will
773    * be bound.
774    *
775    * @throws boost::system::system_error Thrown on failure.
776    *
777    * @par Example
778    * @code
779    * boost::asio::ip::tcp::socket socket(my_context);
780    * socket.open(boost::asio::ip::tcp::v4());
781    * socket.bind(boost::asio::ip::tcp::endpoint(
782    *       boost::asio::ip::tcp::v4(), 12345));
783    * @endcode
784    */
bind(const endpoint_type & endpoint)785   void bind(const endpoint_type& endpoint)
786   {
787     boost::system::error_code ec;
788     impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);
789     boost::asio::detail::throw_error(ec, "bind");
790   }
791 
792   /// Bind the socket to the given local endpoint.
793   /**
794    * This function binds the socket to the specified endpoint on the local
795    * machine.
796    *
797    * @param endpoint An endpoint on the local machine to which the socket will
798    * be bound.
799    *
800    * @param ec Set to indicate what error occurred, if any.
801    *
802    * @par Example
803    * @code
804    * boost::asio::ip::tcp::socket socket(my_context);
805    * socket.open(boost::asio::ip::tcp::v4());
806    * boost::system::error_code ec;
807    * socket.bind(boost::asio::ip::tcp::endpoint(
808    *       boost::asio::ip::tcp::v4(), 12345), ec);
809    * if (ec)
810    * {
811    *   // An error occurred.
812    * }
813    * @endcode
814    */
bind(const endpoint_type & endpoint,boost::system::error_code & ec)815   BOOST_ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint,
816       boost::system::error_code& ec)
817   {
818     impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);
819     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
820   }
821 
822   /// Connect the socket to the specified endpoint.
823   /**
824    * This function is used to connect a socket to the specified remote endpoint.
825    * The function call will block until the connection is successfully made or
826    * an error occurs.
827    *
828    * The socket is automatically opened if it is not already open. If the
829    * connect fails, and the socket was automatically opened, the socket is
830    * not returned to the closed state.
831    *
832    * @param peer_endpoint The remote endpoint to which the socket will be
833    * connected.
834    *
835    * @throws boost::system::system_error Thrown on failure.
836    *
837    * @par Example
838    * @code
839    * boost::asio::ip::tcp::socket socket(my_context);
840    * boost::asio::ip::tcp::endpoint endpoint(
841    *     boost::asio::ip::address::from_string("1.2.3.4"), 12345);
842    * socket.connect(endpoint);
843    * @endcode
844    */
connect(const endpoint_type & peer_endpoint)845   void connect(const endpoint_type& peer_endpoint)
846   {
847     boost::system::error_code ec;
848     if (!is_open())
849     {
850       impl_.get_service().open(impl_.get_implementation(),
851           peer_endpoint.protocol(), ec);
852       boost::asio::detail::throw_error(ec, "connect");
853     }
854     impl_.get_service().connect(impl_.get_implementation(), peer_endpoint, ec);
855     boost::asio::detail::throw_error(ec, "connect");
856   }
857 
858   /// Connect the socket to the specified endpoint.
859   /**
860    * This function is used to connect a socket to the specified remote endpoint.
861    * The function call will block until the connection is successfully made or
862    * an error occurs.
863    *
864    * The socket is automatically opened if it is not already open. If the
865    * connect fails, and the socket was automatically opened, the socket is
866    * not returned to the closed state.
867    *
868    * @param peer_endpoint The remote endpoint to which the socket will be
869    * connected.
870    *
871    * @param ec Set to indicate what error occurred, if any.
872    *
873    * @par Example
874    * @code
875    * boost::asio::ip::tcp::socket socket(my_context);
876    * boost::asio::ip::tcp::endpoint endpoint(
877    *     boost::asio::ip::address::from_string("1.2.3.4"), 12345);
878    * boost::system::error_code ec;
879    * socket.connect(endpoint, ec);
880    * if (ec)
881    * {
882    *   // An error occurred.
883    * }
884    * @endcode
885    */
connect(const endpoint_type & peer_endpoint,boost::system::error_code & ec)886   BOOST_ASIO_SYNC_OP_VOID connect(const endpoint_type& peer_endpoint,
887       boost::system::error_code& ec)
888   {
889     if (!is_open())
890     {
891       impl_.get_service().open(impl_.get_implementation(),
892             peer_endpoint.protocol(), ec);
893       if (ec)
894       {
895         BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
896       }
897     }
898 
899     impl_.get_service().connect(impl_.get_implementation(), peer_endpoint, ec);
900     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
901   }
902 
903   /// Start an asynchronous connect.
904   /**
905    * This function is used to asynchronously connect a socket to the specified
906    * remote endpoint. The function call always returns immediately.
907    *
908    * The socket is automatically opened if it is not already open. If the
909    * connect fails, and the socket was automatically opened, the socket is
910    * not returned to the closed state.
911    *
912    * @param peer_endpoint The remote endpoint to which the socket will be
913    * connected. Copies will be made of the endpoint object as required.
914    *
915    * @param handler The handler to be called when the connection operation
916    * completes. Copies will be made of the handler as required. The function
917    * signature of the handler must be:
918    * @code void handler(
919    *   const boost::system::error_code& error // Result of operation
920    * ); @endcode
921    * Regardless of whether the asynchronous operation completes immediately or
922    * not, the handler will not be invoked from within this function. On
923    * immediate completion, invocation of the handler will be performed in a
924    * manner equivalent to using boost::asio::post().
925    *
926    * @par Example
927    * @code
928    * void connect_handler(const boost::system::error_code& error)
929    * {
930    *   if (!error)
931    *   {
932    *     // Connect succeeded.
933    *   }
934    * }
935    *
936    * ...
937    *
938    * boost::asio::ip::tcp::socket socket(my_context);
939    * boost::asio::ip::tcp::endpoint endpoint(
940    *     boost::asio::ip::address::from_string("1.2.3.4"), 12345);
941    * socket.async_connect(endpoint, connect_handler);
942    * @endcode
943    */
944   template <
945       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code))
946         ConnectHandler BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ConnectHandler,void (boost::system::error_code))947   BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ConnectHandler,
948       void (boost::system::error_code))
949   async_connect(const endpoint_type& peer_endpoint,
950       BOOST_ASIO_MOVE_ARG(ConnectHandler) handler
951         BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
952   {
953     boost::system::error_code open_ec;
954     if (!is_open())
955     {
956       const protocol_type protocol = peer_endpoint.protocol();
957       impl_.get_service().open(impl_.get_implementation(), protocol, open_ec);
958     }
959 
960     return async_initiate<ConnectHandler, void (boost::system::error_code)>(
961         initiate_async_connect(this), handler, peer_endpoint, open_ec);
962   }
963 
964   /// Set an option on the socket.
965   /**
966    * This function is used to set an option on the socket.
967    *
968    * @param option The new option value to be set on the socket.
969    *
970    * @throws boost::system::system_error Thrown on failure.
971    *
972    * @sa SettableSocketOption @n
973    * boost::asio::socket_base::broadcast @n
974    * boost::asio::socket_base::do_not_route @n
975    * boost::asio::socket_base::keep_alive @n
976    * boost::asio::socket_base::linger @n
977    * boost::asio::socket_base::receive_buffer_size @n
978    * boost::asio::socket_base::receive_low_watermark @n
979    * boost::asio::socket_base::reuse_address @n
980    * boost::asio::socket_base::send_buffer_size @n
981    * boost::asio::socket_base::send_low_watermark @n
982    * boost::asio::ip::multicast::join_group @n
983    * boost::asio::ip::multicast::leave_group @n
984    * boost::asio::ip::multicast::enable_loopback @n
985    * boost::asio::ip::multicast::outbound_interface @n
986    * boost::asio::ip::multicast::hops @n
987    * boost::asio::ip::tcp::no_delay
988    *
989    * @par Example
990    * Setting the IPPROTO_TCP/TCP_NODELAY option:
991    * @code
992    * boost::asio::ip::tcp::socket socket(my_context);
993    * ...
994    * boost::asio::ip::tcp::no_delay option(true);
995    * socket.set_option(option);
996    * @endcode
997    */
998   template <typename SettableSocketOption>
set_option(const SettableSocketOption & option)999   void set_option(const SettableSocketOption& option)
1000   {
1001     boost::system::error_code ec;
1002     impl_.get_service().set_option(impl_.get_implementation(), option, ec);
1003     boost::asio::detail::throw_error(ec, "set_option");
1004   }
1005 
1006   /// Set an option on the socket.
1007   /**
1008    * This function is used to set an option on the socket.
1009    *
1010    * @param option The new option value to be set on the socket.
1011    *
1012    * @param ec Set to indicate what error occurred, if any.
1013    *
1014    * @sa SettableSocketOption @n
1015    * boost::asio::socket_base::broadcast @n
1016    * boost::asio::socket_base::do_not_route @n
1017    * boost::asio::socket_base::keep_alive @n
1018    * boost::asio::socket_base::linger @n
1019    * boost::asio::socket_base::receive_buffer_size @n
1020    * boost::asio::socket_base::receive_low_watermark @n
1021    * boost::asio::socket_base::reuse_address @n
1022    * boost::asio::socket_base::send_buffer_size @n
1023    * boost::asio::socket_base::send_low_watermark @n
1024    * boost::asio::ip::multicast::join_group @n
1025    * boost::asio::ip::multicast::leave_group @n
1026    * boost::asio::ip::multicast::enable_loopback @n
1027    * boost::asio::ip::multicast::outbound_interface @n
1028    * boost::asio::ip::multicast::hops @n
1029    * boost::asio::ip::tcp::no_delay
1030    *
1031    * @par Example
1032    * Setting the IPPROTO_TCP/TCP_NODELAY option:
1033    * @code
1034    * boost::asio::ip::tcp::socket socket(my_context);
1035    * ...
1036    * boost::asio::ip::tcp::no_delay option(true);
1037    * boost::system::error_code ec;
1038    * socket.set_option(option, ec);
1039    * if (ec)
1040    * {
1041    *   // An error occurred.
1042    * }
1043    * @endcode
1044    */
1045   template <typename SettableSocketOption>
set_option(const SettableSocketOption & option,boost::system::error_code & ec)1046   BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& option,
1047       boost::system::error_code& ec)
1048   {
1049     impl_.get_service().set_option(impl_.get_implementation(), option, ec);
1050     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1051   }
1052 
1053   /// Get an option from the socket.
1054   /**
1055    * This function is used to get the current value of an option on the socket.
1056    *
1057    * @param option The option value to be obtained from the socket.
1058    *
1059    * @throws boost::system::system_error Thrown on failure.
1060    *
1061    * @sa GettableSocketOption @n
1062    * boost::asio::socket_base::broadcast @n
1063    * boost::asio::socket_base::do_not_route @n
1064    * boost::asio::socket_base::keep_alive @n
1065    * boost::asio::socket_base::linger @n
1066    * boost::asio::socket_base::receive_buffer_size @n
1067    * boost::asio::socket_base::receive_low_watermark @n
1068    * boost::asio::socket_base::reuse_address @n
1069    * boost::asio::socket_base::send_buffer_size @n
1070    * boost::asio::socket_base::send_low_watermark @n
1071    * boost::asio::ip::multicast::join_group @n
1072    * boost::asio::ip::multicast::leave_group @n
1073    * boost::asio::ip::multicast::enable_loopback @n
1074    * boost::asio::ip::multicast::outbound_interface @n
1075    * boost::asio::ip::multicast::hops @n
1076    * boost::asio::ip::tcp::no_delay
1077    *
1078    * @par Example
1079    * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:
1080    * @code
1081    * boost::asio::ip::tcp::socket socket(my_context);
1082    * ...
1083    * boost::asio::ip::tcp::socket::keep_alive option;
1084    * socket.get_option(option);
1085    * bool is_set = option.value();
1086    * @endcode
1087    */
1088   template <typename GettableSocketOption>
get_option(GettableSocketOption & option) const1089   void get_option(GettableSocketOption& option) const
1090   {
1091     boost::system::error_code ec;
1092     impl_.get_service().get_option(impl_.get_implementation(), option, ec);
1093     boost::asio::detail::throw_error(ec, "get_option");
1094   }
1095 
1096   /// Get an option from the socket.
1097   /**
1098    * This function is used to get the current value of an option on the socket.
1099    *
1100    * @param option The option value to be obtained from the socket.
1101    *
1102    * @param ec Set to indicate what error occurred, if any.
1103    *
1104    * @sa GettableSocketOption @n
1105    * boost::asio::socket_base::broadcast @n
1106    * boost::asio::socket_base::do_not_route @n
1107    * boost::asio::socket_base::keep_alive @n
1108    * boost::asio::socket_base::linger @n
1109    * boost::asio::socket_base::receive_buffer_size @n
1110    * boost::asio::socket_base::receive_low_watermark @n
1111    * boost::asio::socket_base::reuse_address @n
1112    * boost::asio::socket_base::send_buffer_size @n
1113    * boost::asio::socket_base::send_low_watermark @n
1114    * boost::asio::ip::multicast::join_group @n
1115    * boost::asio::ip::multicast::leave_group @n
1116    * boost::asio::ip::multicast::enable_loopback @n
1117    * boost::asio::ip::multicast::outbound_interface @n
1118    * boost::asio::ip::multicast::hops @n
1119    * boost::asio::ip::tcp::no_delay
1120    *
1121    * @par Example
1122    * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:
1123    * @code
1124    * boost::asio::ip::tcp::socket socket(my_context);
1125    * ...
1126    * boost::asio::ip::tcp::socket::keep_alive option;
1127    * boost::system::error_code ec;
1128    * socket.get_option(option, ec);
1129    * if (ec)
1130    * {
1131    *   // An error occurred.
1132    * }
1133    * bool is_set = option.value();
1134    * @endcode
1135    */
1136   template <typename GettableSocketOption>
get_option(GettableSocketOption & option,boost::system::error_code & ec) const1137   BOOST_ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option,
1138       boost::system::error_code& ec) const
1139   {
1140     impl_.get_service().get_option(impl_.get_implementation(), option, ec);
1141     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1142   }
1143 
1144   /// Perform an IO control command on the socket.
1145   /**
1146    * This function is used to execute an IO control command on the socket.
1147    *
1148    * @param command The IO control command to be performed on the socket.
1149    *
1150    * @throws boost::system::system_error Thrown on failure.
1151    *
1152    * @sa IoControlCommand @n
1153    * boost::asio::socket_base::bytes_readable @n
1154    * boost::asio::socket_base::non_blocking_io
1155    *
1156    * @par Example
1157    * Getting the number of bytes ready to read:
1158    * @code
1159    * boost::asio::ip::tcp::socket socket(my_context);
1160    * ...
1161    * boost::asio::ip::tcp::socket::bytes_readable command;
1162    * socket.io_control(command);
1163    * std::size_t bytes_readable = command.get();
1164    * @endcode
1165    */
1166   template <typename IoControlCommand>
io_control(IoControlCommand & command)1167   void io_control(IoControlCommand& command)
1168   {
1169     boost::system::error_code ec;
1170     impl_.get_service().io_control(impl_.get_implementation(), command, ec);
1171     boost::asio::detail::throw_error(ec, "io_control");
1172   }
1173 
1174   /// Perform an IO control command on the socket.
1175   /**
1176    * This function is used to execute an IO control command on the socket.
1177    *
1178    * @param command The IO control command to be performed on the socket.
1179    *
1180    * @param ec Set to indicate what error occurred, if any.
1181    *
1182    * @sa IoControlCommand @n
1183    * boost::asio::socket_base::bytes_readable @n
1184    * boost::asio::socket_base::non_blocking_io
1185    *
1186    * @par Example
1187    * Getting the number of bytes ready to read:
1188    * @code
1189    * boost::asio::ip::tcp::socket socket(my_context);
1190    * ...
1191    * boost::asio::ip::tcp::socket::bytes_readable command;
1192    * boost::system::error_code ec;
1193    * socket.io_control(command, ec);
1194    * if (ec)
1195    * {
1196    *   // An error occurred.
1197    * }
1198    * std::size_t bytes_readable = command.get();
1199    * @endcode
1200    */
1201   template <typename IoControlCommand>
io_control(IoControlCommand & command,boost::system::error_code & ec)1202   BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command,
1203       boost::system::error_code& ec)
1204   {
1205     impl_.get_service().io_control(impl_.get_implementation(), command, ec);
1206     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1207   }
1208 
1209   /// Gets the non-blocking mode of the socket.
1210   /**
1211    * @returns @c true if the socket's synchronous operations will fail with
1212    * boost::asio::error::would_block if they are unable to perform the requested
1213    * operation immediately. If @c false, synchronous operations will block
1214    * until complete.
1215    *
1216    * @note The non-blocking mode has no effect on the behaviour of asynchronous
1217    * operations. Asynchronous operations will never fail with the error
1218    * boost::asio::error::would_block.
1219    */
non_blocking() const1220   bool non_blocking() const
1221   {
1222     return impl_.get_service().non_blocking(impl_.get_implementation());
1223   }
1224 
1225   /// Sets the non-blocking mode of the socket.
1226   /**
1227    * @param mode If @c true, the socket's synchronous operations will fail with
1228    * boost::asio::error::would_block if they are unable to perform the requested
1229    * operation immediately. If @c false, synchronous operations will block
1230    * until complete.
1231    *
1232    * @throws boost::system::system_error Thrown on failure.
1233    *
1234    * @note The non-blocking mode has no effect on the behaviour of asynchronous
1235    * operations. Asynchronous operations will never fail with the error
1236    * boost::asio::error::would_block.
1237    */
non_blocking(bool mode)1238   void non_blocking(bool mode)
1239   {
1240     boost::system::error_code ec;
1241     impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec);
1242     boost::asio::detail::throw_error(ec, "non_blocking");
1243   }
1244 
1245   /// Sets the non-blocking mode of the socket.
1246   /**
1247    * @param mode If @c true, the socket's synchronous operations will fail with
1248    * boost::asio::error::would_block if they are unable to perform the requested
1249    * operation immediately. If @c false, synchronous operations will block
1250    * until complete.
1251    *
1252    * @param ec Set to indicate what error occurred, if any.
1253    *
1254    * @note The non-blocking mode has no effect on the behaviour of asynchronous
1255    * operations. Asynchronous operations will never fail with the error
1256    * boost::asio::error::would_block.
1257    */
non_blocking(bool mode,boost::system::error_code & ec)1258   BOOST_ASIO_SYNC_OP_VOID non_blocking(
1259       bool mode, boost::system::error_code& ec)
1260   {
1261     impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec);
1262     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1263   }
1264 
1265   /// Gets the non-blocking mode of the native socket implementation.
1266   /**
1267    * This function is used to retrieve the non-blocking mode of the underlying
1268    * native socket. This mode has no effect on the behaviour of the socket
1269    * object's synchronous operations.
1270    *
1271    * @returns @c true if the underlying socket is in non-blocking mode and
1272    * direct system calls may fail with boost::asio::error::would_block (or the
1273    * equivalent system error).
1274    *
1275    * @note The current non-blocking mode is cached by the socket object.
1276    * Consequently, the return value may be incorrect if the non-blocking mode
1277    * was set directly on the native socket.
1278    *
1279    * @par Example
1280    * This function is intended to allow the encapsulation of arbitrary
1281    * non-blocking system calls as asynchronous operations, in a way that is
1282    * transparent to the user of the socket object. The following example
1283    * illustrates how Linux's @c sendfile system call might be encapsulated:
1284    * @code template <typename Handler>
1285    * struct sendfile_op
1286    * {
1287    *   tcp::socket& sock_;
1288    *   int fd_;
1289    *   Handler handler_;
1290    *   off_t offset_;
1291    *   std::size_t total_bytes_transferred_;
1292    *
1293    *   // Function call operator meeting WriteHandler requirements.
1294    *   // Used as the handler for the async_write_some operation.
1295    *   void operator()(boost::system::error_code ec, std::size_t)
1296    *   {
1297    *     // Put the underlying socket into non-blocking mode.
1298    *     if (!ec)
1299    *       if (!sock_.native_non_blocking())
1300    *         sock_.native_non_blocking(true, ec);
1301    *
1302    *     if (!ec)
1303    *     {
1304    *       for (;;)
1305    *       {
1306    *         // Try the system call.
1307    *         errno = 0;
1308    *         int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);
1309    *         ec = boost::system::error_code(n < 0 ? errno : 0,
1310    *             boost::asio::error::get_system_category());
1311    *         total_bytes_transferred_ += ec ? 0 : n;
1312    *
1313    *         // Retry operation immediately if interrupted by signal.
1314    *         if (ec == boost::asio::error::interrupted)
1315    *           continue;
1316    *
1317    *         // Check if we need to run the operation again.
1318    *         if (ec == boost::asio::error::would_block
1319    *             || ec == boost::asio::error::try_again)
1320    *         {
1321    *           // We have to wait for the socket to become ready again.
1322    *           sock_.async_wait(tcp::socket::wait_write, *this);
1323    *           return;
1324    *         }
1325    *
1326    *         if (ec || n == 0)
1327    *         {
1328    *           // An error occurred, or we have reached the end of the file.
1329    *           // Either way we must exit the loop so we can call the handler.
1330    *           break;
1331    *         }
1332    *
1333    *         // Loop around to try calling sendfile again.
1334    *       }
1335    *     }
1336    *
1337    *     // Pass result back to user's handler.
1338    *     handler_(ec, total_bytes_transferred_);
1339    *   }
1340    * };
1341    *
1342    * template <typename Handler>
1343    * void async_sendfile(tcp::socket& sock, int fd, Handler h)
1344    * {
1345    *   sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
1346    *   sock.async_wait(tcp::socket::wait_write, op);
1347    * } @endcode
1348    */
native_non_blocking() const1349   bool native_non_blocking() const
1350   {
1351     return impl_.get_service().native_non_blocking(impl_.get_implementation());
1352   }
1353 
1354   /// Sets the non-blocking mode of the native socket implementation.
1355   /**
1356    * This function is used to modify the non-blocking mode of the underlying
1357    * native socket. It has no effect on the behaviour of the socket object's
1358    * synchronous operations.
1359    *
1360    * @param mode If @c true, the underlying socket is put into non-blocking
1361    * mode and direct system calls may fail with boost::asio::error::would_block
1362    * (or the equivalent system error).
1363    *
1364    * @throws boost::system::system_error Thrown on failure. If the @c mode is
1365    * @c false, but the current value of @c non_blocking() is @c true, this
1366    * function fails with boost::asio::error::invalid_argument, as the
1367    * combination does not make sense.
1368    *
1369    * @par Example
1370    * This function is intended to allow the encapsulation of arbitrary
1371    * non-blocking system calls as asynchronous operations, in a way that is
1372    * transparent to the user of the socket object. The following example
1373    * illustrates how Linux's @c sendfile system call might be encapsulated:
1374    * @code template <typename Handler>
1375    * struct sendfile_op
1376    * {
1377    *   tcp::socket& sock_;
1378    *   int fd_;
1379    *   Handler handler_;
1380    *   off_t offset_;
1381    *   std::size_t total_bytes_transferred_;
1382    *
1383    *   // Function call operator meeting WriteHandler requirements.
1384    *   // Used as the handler for the async_write_some operation.
1385    *   void operator()(boost::system::error_code ec, std::size_t)
1386    *   {
1387    *     // Put the underlying socket into non-blocking mode.
1388    *     if (!ec)
1389    *       if (!sock_.native_non_blocking())
1390    *         sock_.native_non_blocking(true, ec);
1391    *
1392    *     if (!ec)
1393    *     {
1394    *       for (;;)
1395    *       {
1396    *         // Try the system call.
1397    *         errno = 0;
1398    *         int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);
1399    *         ec = boost::system::error_code(n < 0 ? errno : 0,
1400    *             boost::asio::error::get_system_category());
1401    *         total_bytes_transferred_ += ec ? 0 : n;
1402    *
1403    *         // Retry operation immediately if interrupted by signal.
1404    *         if (ec == boost::asio::error::interrupted)
1405    *           continue;
1406    *
1407    *         // Check if we need to run the operation again.
1408    *         if (ec == boost::asio::error::would_block
1409    *             || ec == boost::asio::error::try_again)
1410    *         {
1411    *           // We have to wait for the socket to become ready again.
1412    *           sock_.async_wait(tcp::socket::wait_write, *this);
1413    *           return;
1414    *         }
1415    *
1416    *         if (ec || n == 0)
1417    *         {
1418    *           // An error occurred, or we have reached the end of the file.
1419    *           // Either way we must exit the loop so we can call the handler.
1420    *           break;
1421    *         }
1422    *
1423    *         // Loop around to try calling sendfile again.
1424    *       }
1425    *     }
1426    *
1427    *     // Pass result back to user's handler.
1428    *     handler_(ec, total_bytes_transferred_);
1429    *   }
1430    * };
1431    *
1432    * template <typename Handler>
1433    * void async_sendfile(tcp::socket& sock, int fd, Handler h)
1434    * {
1435    *   sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
1436    *   sock.async_wait(tcp::socket::wait_write, op);
1437    * } @endcode
1438    */
native_non_blocking(bool mode)1439   void native_non_blocking(bool mode)
1440   {
1441     boost::system::error_code ec;
1442     impl_.get_service().native_non_blocking(
1443         impl_.get_implementation(), mode, ec);
1444     boost::asio::detail::throw_error(ec, "native_non_blocking");
1445   }
1446 
1447   /// Sets the non-blocking mode of the native socket implementation.
1448   /**
1449    * This function is used to modify the non-blocking mode of the underlying
1450    * native socket. It has no effect on the behaviour of the socket object's
1451    * synchronous operations.
1452    *
1453    * @param mode If @c true, the underlying socket is put into non-blocking
1454    * mode and direct system calls may fail with boost::asio::error::would_block
1455    * (or the equivalent system error).
1456    *
1457    * @param ec Set to indicate what error occurred, if any. If the @c mode is
1458    * @c false, but the current value of @c non_blocking() is @c true, this
1459    * function fails with boost::asio::error::invalid_argument, as the
1460    * combination does not make sense.
1461    *
1462    * @par Example
1463    * This function is intended to allow the encapsulation of arbitrary
1464    * non-blocking system calls as asynchronous operations, in a way that is
1465    * transparent to the user of the socket object. The following example
1466    * illustrates how Linux's @c sendfile system call might be encapsulated:
1467    * @code template <typename Handler>
1468    * struct sendfile_op
1469    * {
1470    *   tcp::socket& sock_;
1471    *   int fd_;
1472    *   Handler handler_;
1473    *   off_t offset_;
1474    *   std::size_t total_bytes_transferred_;
1475    *
1476    *   // Function call operator meeting WriteHandler requirements.
1477    *   // Used as the handler for the async_write_some operation.
1478    *   void operator()(boost::system::error_code ec, std::size_t)
1479    *   {
1480    *     // Put the underlying socket into non-blocking mode.
1481    *     if (!ec)
1482    *       if (!sock_.native_non_blocking())
1483    *         sock_.native_non_blocking(true, ec);
1484    *
1485    *     if (!ec)
1486    *     {
1487    *       for (;;)
1488    *       {
1489    *         // Try the system call.
1490    *         errno = 0;
1491    *         int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);
1492    *         ec = boost::system::error_code(n < 0 ? errno : 0,
1493    *             boost::asio::error::get_system_category());
1494    *         total_bytes_transferred_ += ec ? 0 : n;
1495    *
1496    *         // Retry operation immediately if interrupted by signal.
1497    *         if (ec == boost::asio::error::interrupted)
1498    *           continue;
1499    *
1500    *         // Check if we need to run the operation again.
1501    *         if (ec == boost::asio::error::would_block
1502    *             || ec == boost::asio::error::try_again)
1503    *         {
1504    *           // We have to wait for the socket to become ready again.
1505    *           sock_.async_wait(tcp::socket::wait_write, *this);
1506    *           return;
1507    *         }
1508    *
1509    *         if (ec || n == 0)
1510    *         {
1511    *           // An error occurred, or we have reached the end of the file.
1512    *           // Either way we must exit the loop so we can call the handler.
1513    *           break;
1514    *         }
1515    *
1516    *         // Loop around to try calling sendfile again.
1517    *       }
1518    *     }
1519    *
1520    *     // Pass result back to user's handler.
1521    *     handler_(ec, total_bytes_transferred_);
1522    *   }
1523    * };
1524    *
1525    * template <typename Handler>
1526    * void async_sendfile(tcp::socket& sock, int fd, Handler h)
1527    * {
1528    *   sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
1529    *   sock.async_wait(tcp::socket::wait_write, op);
1530    * } @endcode
1531    */
native_non_blocking(bool mode,boost::system::error_code & ec)1532   BOOST_ASIO_SYNC_OP_VOID native_non_blocking(
1533       bool mode, boost::system::error_code& ec)
1534   {
1535     impl_.get_service().native_non_blocking(
1536         impl_.get_implementation(), mode, ec);
1537     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1538   }
1539 
1540   /// Get the local endpoint of the socket.
1541   /**
1542    * This function is used to obtain the locally bound endpoint of the socket.
1543    *
1544    * @returns An object that represents the local endpoint of the socket.
1545    *
1546    * @throws boost::system::system_error Thrown on failure.
1547    *
1548    * @par Example
1549    * @code
1550    * boost::asio::ip::tcp::socket socket(my_context);
1551    * ...
1552    * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint();
1553    * @endcode
1554    */
local_endpoint() const1555   endpoint_type local_endpoint() const
1556   {
1557     boost::system::error_code ec;
1558     endpoint_type ep = impl_.get_service().local_endpoint(
1559         impl_.get_implementation(), ec);
1560     boost::asio::detail::throw_error(ec, "local_endpoint");
1561     return ep;
1562   }
1563 
1564   /// Get the local endpoint of the socket.
1565   /**
1566    * This function is used to obtain the locally bound endpoint of the socket.
1567    *
1568    * @param ec Set to indicate what error occurred, if any.
1569    *
1570    * @returns An object that represents the local endpoint of the socket.
1571    * Returns a default-constructed endpoint object if an error occurred.
1572    *
1573    * @par Example
1574    * @code
1575    * boost::asio::ip::tcp::socket socket(my_context);
1576    * ...
1577    * boost::system::error_code ec;
1578    * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec);
1579    * if (ec)
1580    * {
1581    *   // An error occurred.
1582    * }
1583    * @endcode
1584    */
local_endpoint(boost::system::error_code & ec) const1585   endpoint_type local_endpoint(boost::system::error_code& ec) const
1586   {
1587     return impl_.get_service().local_endpoint(impl_.get_implementation(), ec);
1588   }
1589 
1590   /// Get the remote endpoint of the socket.
1591   /**
1592    * This function is used to obtain the remote endpoint of the socket.
1593    *
1594    * @returns An object that represents the remote endpoint of the socket.
1595    *
1596    * @throws boost::system::system_error Thrown on failure.
1597    *
1598    * @par Example
1599    * @code
1600    * boost::asio::ip::tcp::socket socket(my_context);
1601    * ...
1602    * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint();
1603    * @endcode
1604    */
remote_endpoint() const1605   endpoint_type remote_endpoint() const
1606   {
1607     boost::system::error_code ec;
1608     endpoint_type ep = impl_.get_service().remote_endpoint(
1609         impl_.get_implementation(), ec);
1610     boost::asio::detail::throw_error(ec, "remote_endpoint");
1611     return ep;
1612   }
1613 
1614   /// Get the remote endpoint of the socket.
1615   /**
1616    * This function is used to obtain the remote endpoint of the socket.
1617    *
1618    * @param ec Set to indicate what error occurred, if any.
1619    *
1620    * @returns An object that represents the remote endpoint of the socket.
1621    * Returns a default-constructed endpoint object if an error occurred.
1622    *
1623    * @par Example
1624    * @code
1625    * boost::asio::ip::tcp::socket socket(my_context);
1626    * ...
1627    * boost::system::error_code ec;
1628    * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec);
1629    * if (ec)
1630    * {
1631    *   // An error occurred.
1632    * }
1633    * @endcode
1634    */
remote_endpoint(boost::system::error_code & ec) const1635   endpoint_type remote_endpoint(boost::system::error_code& ec) const
1636   {
1637     return impl_.get_service().remote_endpoint(impl_.get_implementation(), ec);
1638   }
1639 
1640   /// Disable sends or receives on the socket.
1641   /**
1642    * This function is used to disable send operations, receive operations, or
1643    * both.
1644    *
1645    * @param what Determines what types of operation will no longer be allowed.
1646    *
1647    * @throws boost::system::system_error Thrown on failure.
1648    *
1649    * @par Example
1650    * Shutting down the send side of the socket:
1651    * @code
1652    * boost::asio::ip::tcp::socket socket(my_context);
1653    * ...
1654    * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send);
1655    * @endcode
1656    */
shutdown(shutdown_type what)1657   void shutdown(shutdown_type what)
1658   {
1659     boost::system::error_code ec;
1660     impl_.get_service().shutdown(impl_.get_implementation(), what, ec);
1661     boost::asio::detail::throw_error(ec, "shutdown");
1662   }
1663 
1664   /// Disable sends or receives on the socket.
1665   /**
1666    * This function is used to disable send operations, receive operations, or
1667    * both.
1668    *
1669    * @param what Determines what types of operation will no longer be allowed.
1670    *
1671    * @param ec Set to indicate what error occurred, if any.
1672    *
1673    * @par Example
1674    * Shutting down the send side of the socket:
1675    * @code
1676    * boost::asio::ip::tcp::socket socket(my_context);
1677    * ...
1678    * boost::system::error_code ec;
1679    * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec);
1680    * if (ec)
1681    * {
1682    *   // An error occurred.
1683    * }
1684    * @endcode
1685    */
shutdown(shutdown_type what,boost::system::error_code & ec)1686   BOOST_ASIO_SYNC_OP_VOID shutdown(shutdown_type what,
1687       boost::system::error_code& ec)
1688   {
1689     impl_.get_service().shutdown(impl_.get_implementation(), what, ec);
1690     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1691   }
1692 
1693   /// Wait for the socket to become ready to read, ready to write, or to have
1694   /// pending error conditions.
1695   /**
1696    * This function is used to perform a blocking wait for a socket to enter
1697    * a ready to read, write or error condition state.
1698    *
1699    * @param w Specifies the desired socket state.
1700    *
1701    * @par Example
1702    * Waiting for a socket to become readable.
1703    * @code
1704    * boost::asio::ip::tcp::socket socket(my_context);
1705    * ...
1706    * socket.wait(boost::asio::ip::tcp::socket::wait_read);
1707    * @endcode
1708    */
wait(wait_type w)1709   void wait(wait_type w)
1710   {
1711     boost::system::error_code ec;
1712     impl_.get_service().wait(impl_.get_implementation(), w, ec);
1713     boost::asio::detail::throw_error(ec, "wait");
1714   }
1715 
1716   /// Wait for the socket to become ready to read, ready to write, or to have
1717   /// pending error conditions.
1718   /**
1719    * This function is used to perform a blocking wait for a socket to enter
1720    * a ready to read, write or error condition state.
1721    *
1722    * @param w Specifies the desired socket state.
1723    *
1724    * @param ec Set to indicate what error occurred, if any.
1725    *
1726    * @par Example
1727    * Waiting for a socket to become readable.
1728    * @code
1729    * boost::asio::ip::tcp::socket socket(my_context);
1730    * ...
1731    * boost::system::error_code ec;
1732    * socket.wait(boost::asio::ip::tcp::socket::wait_read, ec);
1733    * @endcode
1734    */
wait(wait_type w,boost::system::error_code & ec)1735   BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec)
1736   {
1737     impl_.get_service().wait(impl_.get_implementation(), w, ec);
1738     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1739   }
1740 
1741   /// Asynchronously wait for the socket to become ready to read, ready to
1742   /// write, or to have pending error conditions.
1743   /**
1744    * This function is used to perform an asynchronous wait for a socket to enter
1745    * a ready to read, write or error condition state.
1746    *
1747    * @param w Specifies the desired socket state.
1748    *
1749    * @param handler The handler to be called when the wait operation completes.
1750    * Copies will be made of the handler as required. The function signature of
1751    * the handler must be:
1752    * @code void handler(
1753    *   const boost::system::error_code& error // Result of operation
1754    * ); @endcode
1755    * Regardless of whether the asynchronous operation completes immediately or
1756    * not, the handler will not be invoked from within this function. On
1757    * immediate completion, invocation of the handler will be performed in a
1758    * manner equivalent to using boost::asio::post().
1759    *
1760    * @par Example
1761    * @code
1762    * void wait_handler(const boost::system::error_code& error)
1763    * {
1764    *   if (!error)
1765    *   {
1766    *     // Wait succeeded.
1767    *   }
1768    * }
1769    *
1770    * ...
1771    *
1772    * boost::asio::ip::tcp::socket socket(my_context);
1773    * ...
1774    * socket.async_wait(boost::asio::ip::tcp::socket::wait_read, wait_handler);
1775    * @endcode
1776    */
1777   template <
1778       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code))
1779         WaitHandler BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler,void (boost::system::error_code))1780   BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler,
1781       void (boost::system::error_code))
1782   async_wait(wait_type w,
1783       BOOST_ASIO_MOVE_ARG(WaitHandler) handler
1784         BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
1785   {
1786     return async_initiate<WaitHandler, void (boost::system::error_code)>(
1787         initiate_async_wait(this), handler, w);
1788   }
1789 
1790 protected:
1791   /// Protected destructor to prevent deletion through this type.
1792   /**
1793    * This function destroys the socket, cancelling any outstanding asynchronous
1794    * operations associated with the socket as if by calling @c cancel.
1795    */
~basic_socket()1796   ~basic_socket()
1797   {
1798   }
1799 
1800 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
1801   detail::io_object_impl<
1802     detail::null_socket_service<Protocol>, Executor> impl_;
1803 #elif defined(BOOST_ASIO_HAS_IOCP)
1804   detail::io_object_impl<
1805     detail::win_iocp_socket_service<Protocol>, Executor> impl_;
1806 #else
1807   detail::io_object_impl<
1808     detail::reactive_socket_service<Protocol>, Executor> impl_;
1809 #endif
1810 
1811 private:
1812   // Disallow copying and assignment.
1813   basic_socket(const basic_socket&) BOOST_ASIO_DELETED;
1814   basic_socket& operator=(const basic_socket&) BOOST_ASIO_DELETED;
1815 
1816   class initiate_async_connect
1817   {
1818   public:
1819     typedef Executor executor_type;
1820 
initiate_async_connect(basic_socket * self)1821     explicit initiate_async_connect(basic_socket* self)
1822       : self_(self)
1823     {
1824     }
1825 
get_executor() const1826     executor_type get_executor() const BOOST_ASIO_NOEXCEPT
1827     {
1828       return self_->get_executor();
1829     }
1830 
1831     template <typename ConnectHandler>
operator ()(BOOST_ASIO_MOVE_ARG (ConnectHandler)handler,const endpoint_type & peer_endpoint,const boost::system::error_code & open_ec) const1832     void operator()(BOOST_ASIO_MOVE_ARG(ConnectHandler) handler,
1833         const endpoint_type& peer_endpoint,
1834         const boost::system::error_code& open_ec) const
1835     {
1836       // If you get an error on the following line it means that your handler
1837       // does not meet the documented type requirements for a ConnectHandler.
1838       BOOST_ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check;
1839 
1840       if (open_ec)
1841       {
1842           boost::asio::post(self_->impl_.get_executor(),
1843               boost::asio::detail::bind_handler(
1844                 BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler), open_ec));
1845       }
1846       else
1847       {
1848         detail::non_const_lvalue<ConnectHandler> handler2(handler);
1849         self_->impl_.get_service().async_connect(
1850             self_->impl_.get_implementation(), peer_endpoint,
1851             handler2.value, self_->impl_.get_executor());
1852       }
1853     }
1854 
1855   private:
1856     basic_socket* self_;
1857   };
1858 
1859   class initiate_async_wait
1860   {
1861   public:
1862     typedef Executor executor_type;
1863 
initiate_async_wait(basic_socket * self)1864     explicit initiate_async_wait(basic_socket* self)
1865       : self_(self)
1866     {
1867     }
1868 
get_executor() const1869     executor_type get_executor() const BOOST_ASIO_NOEXCEPT
1870     {
1871       return self_->get_executor();
1872     }
1873 
1874     template <typename WaitHandler>
operator ()(BOOST_ASIO_MOVE_ARG (WaitHandler)handler,wait_type w) const1875     void operator()(BOOST_ASIO_MOVE_ARG(WaitHandler) handler, wait_type w) const
1876     {
1877       // If you get an error on the following line it means that your handler
1878       // does not meet the documented type requirements for a WaitHandler.
1879       BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
1880 
1881       detail::non_const_lvalue<WaitHandler> handler2(handler);
1882       self_->impl_.get_service().async_wait(
1883           self_->impl_.get_implementation(), w,
1884           handler2.value, self_->impl_.get_executor());
1885     }
1886 
1887   private:
1888     basic_socket* self_;
1889   };
1890 };
1891 
1892 } // namespace asio
1893 } // namespace boost
1894 
1895 #include <boost/asio/detail/pop_options.hpp>
1896 
1897 #endif // BOOST_ASIO_BASIC_SOCKET_HPP
1898