• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // basic_socket_ext.hpp
3 // ~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 // Copyright (c) 2018,2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
7 //
8 // Distributed under the Boost Software License, Version 1.0. (See accompanying
9 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10 //
11 
12 #ifndef BOOST_ASIO_BASIC_SOCKET_EXT_HPP
13 #define BOOST_ASIO_BASIC_SOCKET_EXT_HPP
14 
15 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 # pragma once
17 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18 
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/executor.hpp>
29 #include <boost/asio/post.hpp>
30 #include <boost/asio/socket_base.hpp>
31 
32 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
33 # include <boost/asio/detail/null_socket_service.hpp>
34 #elif defined(BOOST_ASIO_HAS_IOCP)
35 # include <boost/asio/detail/win_iocp_socket_service.hpp>
36 #else
37 # include <boost/asio/detail/reactive_socket_service_ext.hpp>
38 #endif
39 
40 #if defined(BOOST_ASIO_HAS_MOVE)
41 # include <utility>
42 #endif // defined(BOOST_ASIO_HAS_MOVE)
43 
44 #include <boost/asio/detail/push_options.hpp>
45 
46 namespace boost {
47 namespace asio {
48 
49 #if !defined(BOOST_ASIO_BASIC_SOCKET_EXT_FWD_DECL)
50 #define BOOST_ASIO_BASIC_SOCKET_EXT_FWD_DECL
51 
52 // Forward declaration with defaulted arguments.
53 template <typename Protocol, typename Executor = executor>
54 class basic_socket_ext;
55 
56 #endif // !defined(BOOST_ASIO_BASIC_SOCKET_EXT_FWD_DECL)
57 
58 /// Provides socket functionality.
59 /**
60  * The basic_socket class template provides functionality that is common to both
61  * stream-oriented and datagram-oriented sockets.
62  *
63  * @par Thread Safety
64  * @e Distinct @e objects: Safe.@n
65  * @e Shared @e objects: Unsafe.
66  */
67 template <typename Protocol, typename Executor>
68 class basic_socket_ext
69   : public socket_base
70 {
71 public:
72   /// The type of the executor associated with the object.
73   typedef Executor executor_type;
74 
75   /// Rebinds the socket type to another executor.
76   template <typename Executor1>
77   struct rebind_executor
78   {
79     /// The socket type when rebound to the specified executor.
80     typedef basic_socket_ext<Protocol, Executor1> other;
81   };
82 
83   /// The native representation of a socket.
84 #if defined(GENERATING_DOCUMENTATION)
85   typedef implementation_defined native_handle_type;
86 #elif defined(BOOST_ASIO_WINDOWS_RUNTIME)
87   typedef typename detail::null_socket_service<
88     Protocol>::native_handle_type native_handle_type;
89 #elif defined(BOOST_ASIO_HAS_IOCP)
90   typedef typename detail::win_iocp_socket_service<
91     Protocol>::native_handle_type native_handle_type;
92 #else
93   typedef typename detail::reactive_socket_service_ext<
94     Protocol>::native_handle_type native_handle_type;
95 #endif
96 
97   /// The protocol type.
98   typedef Protocol protocol_type;
99 
100   /// The endpoint type.
101   typedef typename Protocol::endpoint endpoint_type;
102 
103 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
104   /// A basic_socket is always the lowest layer.
105   typedef basic_socket_ext<Protocol, Executor> lowest_layer_type;
106 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
107 
108   /// Construct a basic_socket without opening it.
109   /**
110    * This constructor creates a socket without opening it.
111    *
112    * @param ex The I/O executor that the socket will use, by default, to
113    * dispatch handlers for any asynchronous operations performed on the socket.
114    */
basic_socket_ext(const executor_type & ex)115   explicit basic_socket_ext(const executor_type& ex)
116     : impl_(0, ex)
117   {
118   }
119 
120   /// Construct a basic_socket without opening it.
121   /**
122    * This constructor creates a socket without opening it.
123    *
124    * @param context An execution context which provides the I/O executor that
125    * the socket will use, by default, to dispatch handlers for any asynchronous
126    * operations performed on the socket.
127    */
128   template <typename ExecutionContext>
basic_socket_ext(ExecutionContext & context,typename enable_if<is_convertible<ExecutionContext &,execution_context &>::value>::type * =0)129   explicit basic_socket_ext(ExecutionContext& context,
130       typename enable_if<
131         is_convertible<ExecutionContext&, execution_context&>::value
132       >::type* = 0)
133     : impl_(0, 0, context)
134   {
135   }
136 
137   /// Construct and open a basic_socket.
138   /**
139    * This constructor creates and opens a socket.
140    *
141    * @param ex The I/O executor that the socket will use, by default, to
142    * dispatch handlers for any asynchronous operations performed on the socket.
143    *
144    * @param protocol An object specifying protocol parameters to be used.
145    *
146    * @throws boost::system::system_error Thrown on failure.
147    */
basic_socket_ext(const executor_type & ex,const protocol_type & protocol)148   basic_socket_ext(const executor_type& ex, const protocol_type& protocol)
149     : impl_(0, ex)
150   {
151     boost::system::error_code ec;
152     impl_.get_service().open(impl_.get_implementation(), protocol, ec);
153     boost::asio::detail::throw_error(ec, "open");
154   }
155 
156   /// Construct and open a basic_socket.
157   /**
158    * This constructor creates and opens a socket.
159    *
160    * @param context An execution context which provides the I/O executor that
161    * the socket will use, by default, to dispatch handlers for any asynchronous
162    * operations performed on the socket.
163    *
164    * @param protocol An object specifying protocol parameters to be used.
165    *
166    * @throws boost::system::system_error Thrown on failure.
167    */
168   template <typename ExecutionContext>
basic_socket_ext(ExecutionContext & context,const protocol_type & protocol,typename enable_if<is_convertible<ExecutionContext &,execution_context &>::value>::type * =0)169   basic_socket_ext(ExecutionContext& context, const protocol_type& protocol,
170       typename enable_if<
171         is_convertible<ExecutionContext&, execution_context&>::value
172       >::type* = 0)
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_ext(const executor_type & ex,const endpoint_type & endpoint)195   basic_socket_ext(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_ext(ExecutionContext & context,const endpoint_type & endpoint,typename enable_if<is_convertible<ExecutionContext &,execution_context &>::value>::type * =0)223   basic_socket_ext(ExecutionContext& context, const endpoint_type& endpoint,
224       typename enable_if<
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_ext(const executor_type & ex,const protocol_type & protocol,const native_handle_type & native_socket)250   basic_socket_ext(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_ext(ExecutionContext & context,const protocol_type & protocol,const native_handle_type & native_socket,typename enable_if<is_convertible<ExecutionContext &,execution_context &>::value>::type * =0)275   basic_socket_ext(ExecutionContext& context, const protocol_type& protocol,
276       const native_handle_type& native_socket,
277       typename enable_if<
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_ext(basic_socket_ext && other)299   basic_socket_ext(basic_socket_ext&& other)
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_ext && other)314   basic_socket_ext& operator=(basic_socket_ext&& 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_ext;
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_ext(basic_socket_ext<Protocol1,Executor1> && other,typename enable_if<is_convertible<Protocol1,Protocol>::value && is_convertible<Executor1,Executor>::value>::type * =0)335   basic_socket_ext(basic_socket_ext<Protocol1, Executor1>&& other,
336       typename enable_if<
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 enable_if<
356     is_convertible<Protocol1, Protocol>::value
357       && is_convertible<Executor1, Executor>::value,
358     basic_socket_ext&
operator =(basic_socket_ext<Protocol1,Executor1> && other)359   >::type operator=(basic_socket_ext<Protocol1, Executor1> && other)
360   {
361     basic_socket_ext 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 <typename ConnectHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler,void (boost::system::error_code))945   BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler,
946       void (boost::system::error_code))
947   async_connect(const endpoint_type& peer_endpoint,
948       BOOST_ASIO_MOVE_ARG(ConnectHandler) handler)
949   {
950     boost::system::error_code open_ec;
951     if (!is_open())
952     {
953       const protocol_type protocol = peer_endpoint.protocol();
954       impl_.get_service().open(impl_.get_implementation(), protocol, open_ec);
955     }
956 
957     return async_initiate<ConnectHandler, void (boost::system::error_code)>(
958         initiate_async_connect(), handler, this, peer_endpoint, open_ec);
959   }
960 
961   /// Set an option on the socket.
962   /**
963    * This function is used to set an option on the socket.
964    *
965    * @param option The new option value to be set on the socket.
966    *
967    * @throws boost::system::system_error Thrown on failure.
968    *
969    * @sa SettableSocketOption @n
970    * boost::asio::socket_base::broadcast @n
971    * boost::asio::socket_base::do_not_route @n
972    * boost::asio::socket_base::keep_alive @n
973    * boost::asio::socket_base::linger @n
974    * boost::asio::socket_base::receive_buffer_size @n
975    * boost::asio::socket_base::receive_low_watermark @n
976    * boost::asio::socket_base::reuse_address @n
977    * boost::asio::socket_base::send_buffer_size @n
978    * boost::asio::socket_base::send_low_watermark @n
979    * boost::asio::ip::multicast::join_group @n
980    * boost::asio::ip::multicast::leave_group @n
981    * boost::asio::ip::multicast::enable_loopback @n
982    * boost::asio::ip::multicast::outbound_interface @n
983    * boost::asio::ip::multicast::hops @n
984    * boost::asio::ip::tcp::no_delay
985    *
986    * @par Example
987    * Setting the IPPROTO_TCP/TCP_NODELAY option:
988    * @code
989    * boost::asio::ip::tcp::socket socket(my_context);
990    * ...
991    * boost::asio::ip::tcp::no_delay option(true);
992    * socket.set_option(option);
993    * @endcode
994    */
995   template <typename SettableSocketOption>
set_option(const SettableSocketOption & option)996   void set_option(const SettableSocketOption& option)
997   {
998     boost::system::error_code ec;
999     impl_.get_service().set_option(impl_.get_implementation(), option, ec);
1000     boost::asio::detail::throw_error(ec, "set_option");
1001   }
1002 
1003   /// Set an option on the socket.
1004   /**
1005    * This function is used to set an option on the socket.
1006    *
1007    * @param option The new option value to be set on the socket.
1008    *
1009    * @param ec Set to indicate what error occurred, if any.
1010    *
1011    * @sa SettableSocketOption @n
1012    * boost::asio::socket_base::broadcast @n
1013    * boost::asio::socket_base::do_not_route @n
1014    * boost::asio::socket_base::keep_alive @n
1015    * boost::asio::socket_base::linger @n
1016    * boost::asio::socket_base::receive_buffer_size @n
1017    * boost::asio::socket_base::receive_low_watermark @n
1018    * boost::asio::socket_base::reuse_address @n
1019    * boost::asio::socket_base::send_buffer_size @n
1020    * boost::asio::socket_base::send_low_watermark @n
1021    * boost::asio::ip::multicast::join_group @n
1022    * boost::asio::ip::multicast::leave_group @n
1023    * boost::asio::ip::multicast::enable_loopback @n
1024    * boost::asio::ip::multicast::outbound_interface @n
1025    * boost::asio::ip::multicast::hops @n
1026    * boost::asio::ip::tcp::no_delay
1027    *
1028    * @par Example
1029    * Setting the IPPROTO_TCP/TCP_NODELAY option:
1030    * @code
1031    * boost::asio::ip::tcp::socket socket(my_context);
1032    * ...
1033    * boost::asio::ip::tcp::no_delay option(true);
1034    * boost::system::error_code ec;
1035    * socket.set_option(option, ec);
1036    * if (ec)
1037    * {
1038    *   // An error occurred.
1039    * }
1040    * @endcode
1041    */
1042   template <typename SettableSocketOption>
set_option(const SettableSocketOption & option,boost::system::error_code & ec)1043   BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& option,
1044       boost::system::error_code& ec)
1045   {
1046     impl_.get_service().set_option(impl_.get_implementation(), option, ec);
1047     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1048   }
1049 
1050   /// Get an option from the socket.
1051   /**
1052    * This function is used to get the current value of an option on the socket.
1053    *
1054    * @param option The option value to be obtained from the socket.
1055    *
1056    * @throws boost::system::system_error Thrown on failure.
1057    *
1058    * @sa GettableSocketOption @n
1059    * boost::asio::socket_base::broadcast @n
1060    * boost::asio::socket_base::do_not_route @n
1061    * boost::asio::socket_base::keep_alive @n
1062    * boost::asio::socket_base::linger @n
1063    * boost::asio::socket_base::receive_buffer_size @n
1064    * boost::asio::socket_base::receive_low_watermark @n
1065    * boost::asio::socket_base::reuse_address @n
1066    * boost::asio::socket_base::send_buffer_size @n
1067    * boost::asio::socket_base::send_low_watermark @n
1068    * boost::asio::ip::multicast::join_group @n
1069    * boost::asio::ip::multicast::leave_group @n
1070    * boost::asio::ip::multicast::enable_loopback @n
1071    * boost::asio::ip::multicast::outbound_interface @n
1072    * boost::asio::ip::multicast::hops @n
1073    * boost::asio::ip::tcp::no_delay
1074    *
1075    * @par Example
1076    * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:
1077    * @code
1078    * boost::asio::ip::tcp::socket socket(my_context);
1079    * ...
1080    * boost::asio::ip::tcp::socket::keep_alive option;
1081    * socket.get_option(option);
1082    * bool is_set = option.value();
1083    * @endcode
1084    */
1085   template <typename GettableSocketOption>
get_option(GettableSocketOption & option) const1086   void get_option(GettableSocketOption& option) const
1087   {
1088     boost::system::error_code ec;
1089     impl_.get_service().get_option(impl_.get_implementation(), option, ec);
1090     boost::asio::detail::throw_error(ec, "get_option");
1091   }
1092 
1093   /// Get an option from the socket.
1094   /**
1095    * This function is used to get the current value of an option on the socket.
1096    *
1097    * @param option The option value to be obtained from the socket.
1098    *
1099    * @param ec Set to indicate what error occurred, if any.
1100    *
1101    * @sa GettableSocketOption @n
1102    * boost::asio::socket_base::broadcast @n
1103    * boost::asio::socket_base::do_not_route @n
1104    * boost::asio::socket_base::keep_alive @n
1105    * boost::asio::socket_base::linger @n
1106    * boost::asio::socket_base::receive_buffer_size @n
1107    * boost::asio::socket_base::receive_low_watermark @n
1108    * boost::asio::socket_base::reuse_address @n
1109    * boost::asio::socket_base::send_buffer_size @n
1110    * boost::asio::socket_base::send_low_watermark @n
1111    * boost::asio::ip::multicast::join_group @n
1112    * boost::asio::ip::multicast::leave_group @n
1113    * boost::asio::ip::multicast::enable_loopback @n
1114    * boost::asio::ip::multicast::outbound_interface @n
1115    * boost::asio::ip::multicast::hops @n
1116    * boost::asio::ip::tcp::no_delay
1117    *
1118    * @par Example
1119    * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:
1120    * @code
1121    * boost::asio::ip::tcp::socket socket(my_context);
1122    * ...
1123    * boost::asio::ip::tcp::socket::keep_alive option;
1124    * boost::system::error_code ec;
1125    * socket.get_option(option, ec);
1126    * if (ec)
1127    * {
1128    *   // An error occurred.
1129    * }
1130    * bool is_set = option.value();
1131    * @endcode
1132    */
1133   template <typename GettableSocketOption>
get_option(GettableSocketOption & option,boost::system::error_code & ec) const1134   BOOST_ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option,
1135       boost::system::error_code& ec) const
1136   {
1137     impl_.get_service().get_option(impl_.get_implementation(), option, ec);
1138     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1139   }
1140 
1141   /// Perform an IO control command on the socket.
1142   /**
1143    * This function is used to execute an IO control command on the socket.
1144    *
1145    * @param command The IO control command to be performed on the socket.
1146    *
1147    * @throws boost::system::system_error Thrown on failure.
1148    *
1149    * @sa IoControlCommand @n
1150    * boost::asio::socket_base::bytes_readable @n
1151    * boost::asio::socket_base::non_blocking_io
1152    *
1153    * @par Example
1154    * Getting the number of bytes ready to read:
1155    * @code
1156    * boost::asio::ip::tcp::socket socket(my_context);
1157    * ...
1158    * boost::asio::ip::tcp::socket::bytes_readable command;
1159    * socket.io_control(command);
1160    * std::size_t bytes_readable = command.get();
1161    * @endcode
1162    */
1163   template <typename IoControlCommand>
io_control(IoControlCommand & command)1164   void io_control(IoControlCommand& command)
1165   {
1166     boost::system::error_code ec;
1167     impl_.get_service().io_control(impl_.get_implementation(), command, ec);
1168     boost::asio::detail::throw_error(ec, "io_control");
1169   }
1170 
1171   /// Perform an IO control command on the socket.
1172   /**
1173    * This function is used to execute an IO control command on the socket.
1174    *
1175    * @param command The IO control command to be performed on the socket.
1176    *
1177    * @param ec Set to indicate what error occurred, if any.
1178    *
1179    * @sa IoControlCommand @n
1180    * boost::asio::socket_base::bytes_readable @n
1181    * boost::asio::socket_base::non_blocking_io
1182    *
1183    * @par Example
1184    * Getting the number of bytes ready to read:
1185    * @code
1186    * boost::asio::ip::tcp::socket socket(my_context);
1187    * ...
1188    * boost::asio::ip::tcp::socket::bytes_readable command;
1189    * boost::system::error_code ec;
1190    * socket.io_control(command, ec);
1191    * if (ec)
1192    * {
1193    *   // An error occurred.
1194    * }
1195    * std::size_t bytes_readable = command.get();
1196    * @endcode
1197    */
1198   template <typename IoControlCommand>
io_control(IoControlCommand & command,boost::system::error_code & ec)1199   BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command,
1200       boost::system::error_code& ec)
1201   {
1202     impl_.get_service().io_control(impl_.get_implementation(), command, ec);
1203     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1204   }
1205 
1206   /// Gets the non-blocking mode of the socket.
1207   /**
1208    * @returns @c true if the socket's synchronous operations will fail with
1209    * boost::asio::error::would_block if they are unable to perform the requested
1210    * operation immediately. If @c false, synchronous operations will block
1211    * until complete.
1212    *
1213    * @note The non-blocking mode has no effect on the behaviour of asynchronous
1214    * operations. Asynchronous operations will never fail with the error
1215    * boost::asio::error::would_block.
1216    */
non_blocking() const1217   bool non_blocking() const
1218   {
1219     return impl_.get_service().non_blocking(impl_.get_implementation());
1220   }
1221 
1222   /// Sets the non-blocking mode of the socket.
1223   /**
1224    * @param mode If @c true, the socket's synchronous operations will fail with
1225    * boost::asio::error::would_block if they are unable to perform the requested
1226    * operation immediately. If @c false, synchronous operations will block
1227    * until complete.
1228    *
1229    * @throws boost::system::system_error Thrown on failure.
1230    *
1231    * @note The non-blocking mode has no effect on the behaviour of asynchronous
1232    * operations. Asynchronous operations will never fail with the error
1233    * boost::asio::error::would_block.
1234    */
non_blocking(bool mode)1235   void non_blocking(bool mode)
1236   {
1237     boost::system::error_code ec;
1238     impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec);
1239     boost::asio::detail::throw_error(ec, "non_blocking");
1240   }
1241 
1242   /// Sets the non-blocking mode of the socket.
1243   /**
1244    * @param mode If @c true, the socket's synchronous operations will fail with
1245    * boost::asio::error::would_block if they are unable to perform the requested
1246    * operation immediately. If @c false, synchronous operations will block
1247    * until complete.
1248    *
1249    * @param ec Set to indicate what error occurred, if any.
1250    *
1251    * @note The non-blocking mode has no effect on the behaviour of asynchronous
1252    * operations. Asynchronous operations will never fail with the error
1253    * boost::asio::error::would_block.
1254    */
non_blocking(bool mode,boost::system::error_code & ec)1255   BOOST_ASIO_SYNC_OP_VOID non_blocking(
1256       bool mode, boost::system::error_code& ec)
1257   {
1258     impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec);
1259     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1260   }
1261 
1262   /// Gets the non-blocking mode of the native socket implementation.
1263   /**
1264    * This function is used to retrieve the non-blocking mode of the underlying
1265    * native socket. This mode has no effect on the behaviour of the socket
1266    * object's synchronous operations.
1267    *
1268    * @returns @c true if the underlying socket is in non-blocking mode and
1269    * direct system calls may fail with boost::asio::error::would_block (or the
1270    * equivalent system error).
1271    *
1272    * @note The current non-blocking mode is cached by the socket object.
1273    * Consequently, the return value may be incorrect if the non-blocking mode
1274    * was set directly on the native socket.
1275    *
1276    * @par Example
1277    * This function is intended to allow the encapsulation of arbitrary
1278    * non-blocking system calls as asynchronous operations, in a way that is
1279    * transparent to the user of the socket object. The following example
1280    * illustrates how Linux's @c sendfile system call might be encapsulated:
1281    * @code template <typename Handler>
1282    * struct sendfile_op
1283    * {
1284    *   tcp::socket& sock_;
1285    *   int fd_;
1286    *   Handler handler_;
1287    *   off_t offset_;
1288    *   std::size_t total_bytes_transferred_;
1289    *
1290    *   // Function call operator meeting WriteHandler requirements.
1291    *   // Used as the handler for the async_write_some operation.
1292    *   void operator()(boost::system::error_code ec, std::size_t)
1293    *   {
1294    *     // Put the underlying socket into non-blocking mode.
1295    *     if (!ec)
1296    *       if (!sock_.native_non_blocking())
1297    *         sock_.native_non_blocking(true, ec);
1298    *
1299    *     if (!ec)
1300    *     {
1301    *       for (;;)
1302    *       {
1303    *         // Try the system call.
1304    *         errno = 0;
1305    *         int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);
1306    *         ec = boost::system::error_code(n < 0 ? errno : 0,
1307    *             boost::asio::error::get_system_category());
1308    *         total_bytes_transferred_ += ec ? 0 : n;
1309    *
1310    *         // Retry operation immediately if interrupted by signal.
1311    *         if (ec == boost::asio::error::interrupted)
1312    *           continue;
1313    *
1314    *         // Check if we need to run the operation again.
1315    *         if (ec == boost::asio::error::would_block
1316    *             || ec == boost::asio::error::try_again)
1317    *         {
1318    *           // We have to wait for the socket to become ready again.
1319    *           sock_.async_wait(tcp::socket::wait_write, *this);
1320    *           return;
1321    *         }
1322    *
1323    *         if (ec || n == 0)
1324    *         {
1325    *           // An error occurred, or we have reached the end of the file.
1326    *           // Either way we must exit the loop so we can call the handler.
1327    *           break;
1328    *         }
1329    *
1330    *         // Loop around to try calling sendfile again.
1331    *       }
1332    *     }
1333    *
1334    *     // Pass result back to user's handler.
1335    *     handler_(ec, total_bytes_transferred_);
1336    *   }
1337    * };
1338    *
1339    * template <typename Handler>
1340    * void async_sendfile(tcp::socket& sock, int fd, Handler h)
1341    * {
1342    *   sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
1343    *   sock.async_wait(tcp::socket::wait_write, op);
1344    * } @endcode
1345    */
native_non_blocking() const1346   bool native_non_blocking() const
1347   {
1348     return impl_.get_service().native_non_blocking(impl_.get_implementation());
1349   }
1350 
1351   /// Sets the non-blocking mode of the native socket implementation.
1352   /**
1353    * This function is used to modify the non-blocking mode of the underlying
1354    * native socket. It has no effect on the behaviour of the socket object's
1355    * synchronous operations.
1356    *
1357    * @param mode If @c true, the underlying socket is put into non-blocking
1358    * mode and direct system calls may fail with boost::asio::error::would_block
1359    * (or the equivalent system error).
1360    *
1361    * @throws boost::system::system_error Thrown on failure. If the @c mode is
1362    * @c false, but the current value of @c non_blocking() is @c true, this
1363    * function fails with boost::asio::error::invalid_argument, as the
1364    * combination does not make sense.
1365    *
1366    * @par Example
1367    * This function is intended to allow the encapsulation of arbitrary
1368    * non-blocking system calls as asynchronous operations, in a way that is
1369    * transparent to the user of the socket object. The following example
1370    * illustrates how Linux's @c sendfile system call might be encapsulated:
1371    * @code template <typename Handler>
1372    * struct sendfile_op
1373    * {
1374    *   tcp::socket& sock_;
1375    *   int fd_;
1376    *   Handler handler_;
1377    *   off_t offset_;
1378    *   std::size_t total_bytes_transferred_;
1379    *
1380    *   // Function call operator meeting WriteHandler requirements.
1381    *   // Used as the handler for the async_write_some operation.
1382    *   void operator()(boost::system::error_code ec, std::size_t)
1383    *   {
1384    *     // Put the underlying socket into non-blocking mode.
1385    *     if (!ec)
1386    *       if (!sock_.native_non_blocking())
1387    *         sock_.native_non_blocking(true, ec);
1388    *
1389    *     if (!ec)
1390    *     {
1391    *       for (;;)
1392    *       {
1393    *         // Try the system call.
1394    *         errno = 0;
1395    *         int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);
1396    *         ec = boost::system::error_code(n < 0 ? errno : 0,
1397    *             boost::asio::error::get_system_category());
1398    *         total_bytes_transferred_ += ec ? 0 : n;
1399    *
1400    *         // Retry operation immediately if interrupted by signal.
1401    *         if (ec == boost::asio::error::interrupted)
1402    *           continue;
1403    *
1404    *         // Check if we need to run the operation again.
1405    *         if (ec == boost::asio::error::would_block
1406    *             || ec == boost::asio::error::try_again)
1407    *         {
1408    *           // We have to wait for the socket to become ready again.
1409    *           sock_.async_wait(tcp::socket::wait_write, *this);
1410    *           return;
1411    *         }
1412    *
1413    *         if (ec || n == 0)
1414    *         {
1415    *           // An error occurred, or we have reached the end of the file.
1416    *           // Either way we must exit the loop so we can call the handler.
1417    *           break;
1418    *         }
1419    *
1420    *         // Loop around to try calling sendfile again.
1421    *       }
1422    *     }
1423    *
1424    *     // Pass result back to user's handler.
1425    *     handler_(ec, total_bytes_transferred_);
1426    *   }
1427    * };
1428    *
1429    * template <typename Handler>
1430    * void async_sendfile(tcp::socket& sock, int fd, Handler h)
1431    * {
1432    *   sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
1433    *   sock.async_wait(tcp::socket::wait_write, op);
1434    * } @endcode
1435    */
native_non_blocking(bool mode)1436   void native_non_blocking(bool mode)
1437   {
1438     boost::system::error_code ec;
1439     impl_.get_service().native_non_blocking(
1440         impl_.get_implementation(), mode, ec);
1441     boost::asio::detail::throw_error(ec, "native_non_blocking");
1442   }
1443 
1444   /// Sets the non-blocking mode of the native socket implementation.
1445   /**
1446    * This function is used to modify the non-blocking mode of the underlying
1447    * native socket. It has no effect on the behaviour of the socket object's
1448    * synchronous operations.
1449    *
1450    * @param mode If @c true, the underlying socket is put into non-blocking
1451    * mode and direct system calls may fail with boost::asio::error::would_block
1452    * (or the equivalent system error).
1453    *
1454    * @param ec Set to indicate what error occurred, if any. If the @c mode is
1455    * @c false, but the current value of @c non_blocking() is @c true, this
1456    * function fails with boost::asio::error::invalid_argument, as the
1457    * combination does not make sense.
1458    *
1459    * @par Example
1460    * This function is intended to allow the encapsulation of arbitrary
1461    * non-blocking system calls as asynchronous operations, in a way that is
1462    * transparent to the user of the socket object. The following example
1463    * illustrates how Linux's @c sendfile system call might be encapsulated:
1464    * @code template <typename Handler>
1465    * struct sendfile_op
1466    * {
1467    *   tcp::socket& sock_;
1468    *   int fd_;
1469    *   Handler handler_;
1470    *   off_t offset_;
1471    *   std::size_t total_bytes_transferred_;
1472    *
1473    *   // Function call operator meeting WriteHandler requirements.
1474    *   // Used as the handler for the async_write_some operation.
1475    *   void operator()(boost::system::error_code ec, std::size_t)
1476    *   {
1477    *     // Put the underlying socket into non-blocking mode.
1478    *     if (!ec)
1479    *       if (!sock_.native_non_blocking())
1480    *         sock_.native_non_blocking(true, ec);
1481    *
1482    *     if (!ec)
1483    *     {
1484    *       for (;;)
1485    *       {
1486    *         // Try the system call.
1487    *         errno = 0;
1488    *         int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);
1489    *         ec = boost::system::error_code(n < 0 ? errno : 0,
1490    *             boost::asio::error::get_system_category());
1491    *         total_bytes_transferred_ += ec ? 0 : n;
1492    *
1493    *         // Retry operation immediately if interrupted by signal.
1494    *         if (ec == boost::asio::error::interrupted)
1495    *           continue;
1496    *
1497    *         // Check if we need to run the operation again.
1498    *         if (ec == boost::asio::error::would_block
1499    *             || ec == boost::asio::error::try_again)
1500    *         {
1501    *           // We have to wait for the socket to become ready again.
1502    *           sock_.async_wait(tcp::socket::wait_write, *this);
1503    *           return;
1504    *         }
1505    *
1506    *         if (ec || n == 0)
1507    *         {
1508    *           // An error occurred, or we have reached the end of the file.
1509    *           // Either way we must exit the loop so we can call the handler.
1510    *           break;
1511    *         }
1512    *
1513    *         // Loop around to try calling sendfile again.
1514    *       }
1515    *     }
1516    *
1517    *     // Pass result back to user's handler.
1518    *     handler_(ec, total_bytes_transferred_);
1519    *   }
1520    * };
1521    *
1522    * template <typename Handler>
1523    * void async_sendfile(tcp::socket& sock, int fd, Handler h)
1524    * {
1525    *   sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
1526    *   sock.async_wait(tcp::socket::wait_write, op);
1527    * } @endcode
1528    */
native_non_blocking(bool mode,boost::system::error_code & ec)1529   BOOST_ASIO_SYNC_OP_VOID native_non_blocking(
1530       bool mode, boost::system::error_code& ec)
1531   {
1532     impl_.get_service().native_non_blocking(
1533         impl_.get_implementation(), mode, ec);
1534     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1535   }
1536 
1537   /// Get the local endpoint of the socket.
1538   /**
1539    * This function is used to obtain the locally bound endpoint of the socket.
1540    *
1541    * @returns An object that represents the local endpoint of the socket.
1542    *
1543    * @throws boost::system::system_error Thrown on failure.
1544    *
1545    * @par Example
1546    * @code
1547    * boost::asio::ip::tcp::socket socket(my_context);
1548    * ...
1549    * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint();
1550    * @endcode
1551    */
local_endpoint() const1552   endpoint_type local_endpoint() const
1553   {
1554     boost::system::error_code ec;
1555     endpoint_type ep = impl_.get_service().local_endpoint(
1556         impl_.get_implementation(), ec);
1557     boost::asio::detail::throw_error(ec, "local_endpoint");
1558     return ep;
1559   }
1560 
1561   /// Get the local endpoint of the socket.
1562   /**
1563    * This function is used to obtain the locally bound endpoint of the socket.
1564    *
1565    * @param ec Set to indicate what error occurred, if any.
1566    *
1567    * @returns An object that represents the local endpoint of the socket.
1568    * Returns a default-constructed endpoint object if an error occurred.
1569    *
1570    * @par Example
1571    * @code
1572    * boost::asio::ip::tcp::socket socket(my_context);
1573    * ...
1574    * boost::system::error_code ec;
1575    * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec);
1576    * if (ec)
1577    * {
1578    *   // An error occurred.
1579    * }
1580    * @endcode
1581    */
local_endpoint(boost::system::error_code & ec) const1582   endpoint_type local_endpoint(boost::system::error_code& ec) const
1583   {
1584     return impl_.get_service().local_endpoint(impl_.get_implementation(), ec);
1585   }
1586 
1587   /// Get the remote endpoint of the socket.
1588   /**
1589    * This function is used to obtain the remote endpoint of the socket.
1590    *
1591    * @returns An object that represents the remote endpoint of the socket.
1592    *
1593    * @throws boost::system::system_error Thrown on failure.
1594    *
1595    * @par Example
1596    * @code
1597    * boost::asio::ip::tcp::socket socket(my_context);
1598    * ...
1599    * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint();
1600    * @endcode
1601    */
remote_endpoint() const1602   endpoint_type remote_endpoint() const
1603   {
1604     boost::system::error_code ec;
1605     endpoint_type ep = impl_.get_service().remote_endpoint(
1606         impl_.get_implementation(), ec);
1607     boost::asio::detail::throw_error(ec, "remote_endpoint");
1608     return ep;
1609   }
1610 
1611   /// Get the remote endpoint of the socket.
1612   /**
1613    * This function is used to obtain the remote endpoint of the socket.
1614    *
1615    * @param ec Set to indicate what error occurred, if any.
1616    *
1617    * @returns An object that represents the remote endpoint of the socket.
1618    * Returns a default-constructed endpoint object if an error occurred.
1619    *
1620    * @par Example
1621    * @code
1622    * boost::asio::ip::tcp::socket socket(my_context);
1623    * ...
1624    * boost::system::error_code ec;
1625    * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec);
1626    * if (ec)
1627    * {
1628    *   // An error occurred.
1629    * }
1630    * @endcode
1631    */
remote_endpoint(boost::system::error_code & ec) const1632   endpoint_type remote_endpoint(boost::system::error_code& ec) const
1633   {
1634     return impl_.get_service().remote_endpoint(impl_.get_implementation(), ec);
1635   }
1636 
1637   /// Disable sends or receives on the socket.
1638   /**
1639    * This function is used to disable send operations, receive operations, or
1640    * both.
1641    *
1642    * @param what Determines what types of operation will no longer be allowed.
1643    *
1644    * @throws boost::system::system_error Thrown on failure.
1645    *
1646    * @par Example
1647    * Shutting down the send side of the socket:
1648    * @code
1649    * boost::asio::ip::tcp::socket socket(my_context);
1650    * ...
1651    * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send);
1652    * @endcode
1653    */
shutdown(shutdown_type what)1654   void shutdown(shutdown_type what)
1655   {
1656     boost::system::error_code ec;
1657     impl_.get_service().shutdown(impl_.get_implementation(), what, ec);
1658     boost::asio::detail::throw_error(ec, "shutdown");
1659   }
1660 
1661   /// Disable sends or receives on the socket.
1662   /**
1663    * This function is used to disable send operations, receive operations, or
1664    * both.
1665    *
1666    * @param what Determines what types of operation will no longer be allowed.
1667    *
1668    * @param ec Set to indicate what error occurred, if any.
1669    *
1670    * @par Example
1671    * Shutting down the send side of the socket:
1672    * @code
1673    * boost::asio::ip::tcp::socket socket(my_context);
1674    * ...
1675    * boost::system::error_code ec;
1676    * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec);
1677    * if (ec)
1678    * {
1679    *   // An error occurred.
1680    * }
1681    * @endcode
1682    */
shutdown(shutdown_type what,boost::system::error_code & ec)1683   BOOST_ASIO_SYNC_OP_VOID shutdown(shutdown_type what,
1684       boost::system::error_code& ec)
1685   {
1686     impl_.get_service().shutdown(impl_.get_implementation(), what, ec);
1687     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1688   }
1689 
1690   /// Wait for the socket to become ready to read, ready to write, or to have
1691   /// pending error conditions.
1692   /**
1693    * This function is used to perform a blocking wait for a socket to enter
1694    * a ready to read, write or error condition state.
1695    *
1696    * @param w Specifies the desired socket state.
1697    *
1698    * @par Example
1699    * Waiting for a socket to become readable.
1700    * @code
1701    * boost::asio::ip::tcp::socket socket(my_context);
1702    * ...
1703    * socket.wait(boost::asio::ip::tcp::socket::wait_read);
1704    * @endcode
1705    */
wait(wait_type w)1706   void wait(wait_type w)
1707   {
1708     boost::system::error_code ec;
1709     impl_.get_service().wait(impl_.get_implementation(), w, ec);
1710     boost::asio::detail::throw_error(ec, "wait");
1711   }
1712 
1713   /// Wait for the socket to become ready to read, ready to write, or to have
1714   /// pending error conditions.
1715   /**
1716    * This function is used to perform a blocking wait for a socket to enter
1717    * a ready to read, write or error condition state.
1718    *
1719    * @param w Specifies the desired socket state.
1720    *
1721    * @param ec Set to indicate what error occurred, if any.
1722    *
1723    * @par Example
1724    * Waiting for a socket to become readable.
1725    * @code
1726    * boost::asio::ip::tcp::socket socket(my_context);
1727    * ...
1728    * boost::system::error_code ec;
1729    * socket.wait(boost::asio::ip::tcp::socket::wait_read, ec);
1730    * @endcode
1731    */
wait(wait_type w,boost::system::error_code & ec)1732   BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec)
1733   {
1734     impl_.get_service().wait(impl_.get_implementation(), w, ec);
1735     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1736   }
1737 
1738   /// Asynchronously wait for the socket to become ready to read, ready to
1739   /// write, or to have pending error conditions.
1740   /**
1741    * This function is used to perform an asynchronous wait for a socket to enter
1742    * a ready to read, write or error condition state.
1743    *
1744    * @param w Specifies the desired socket state.
1745    *
1746    * @param handler The handler to be called when the wait operation completes.
1747    * Copies will be made of the handler as required. The function signature of
1748    * the handler must be:
1749    * @code void handler(
1750    *   const boost::system::error_code& error // Result of operation
1751    * ); @endcode
1752    * Regardless of whether the asynchronous operation completes immediately or
1753    * not, the handler will not be invoked from within this function. On
1754    * immediate completion, invocation of the handler will be performed in a
1755    * manner equivalent to using boost::asio::post().
1756    *
1757    * @par Example
1758    * @code
1759    * void wait_handler(const boost::system::error_code& error)
1760    * {
1761    *   if (!error)
1762    *   {
1763    *     // Wait succeeded.
1764    *   }
1765    * }
1766    *
1767    * ...
1768    *
1769    * boost::asio::ip::tcp::socket socket(my_context);
1770    * ...
1771    * socket.async_wait(boost::asio::ip::tcp::socket::wait_read, wait_handler);
1772    * @endcode
1773    */
1774   template <typename WaitHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,void (boost::system::error_code))1775   BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
1776       void (boost::system::error_code))
1777   async_wait(wait_type w, BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
1778   {
1779     return async_initiate<WaitHandler, void (boost::system::error_code)>(
1780         initiate_async_wait(), handler, this, w);
1781   }
1782 
1783 protected:
1784   /// Protected destructor to prevent deletion through this type.
1785   /**
1786    * This function destroys the socket, cancelling any outstanding asynchronous
1787    * operations associated with the socket as if by calling @c cancel.
1788    */
~basic_socket_ext()1789   ~basic_socket_ext()
1790   {
1791   }
1792 
1793 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
1794   detail::io_object_impl<
1795     detail::null_socket_service<Protocol>, Executor> impl_;
1796 #elif defined(BOOST_ASIO_HAS_IOCP)
1797   detail::io_object_impl<
1798     detail::win_iocp_socket_service<Protocol>, Executor> impl_;
1799 #else
1800   detail::io_object_impl<
1801     detail::reactive_socket_service_ext<Protocol>, Executor> impl_;
1802 #endif
1803 
1804 private:
1805   // Disallow copying and assignment.
1806   basic_socket_ext(const basic_socket_ext&) BOOST_ASIO_DELETED;
1807   basic_socket_ext& operator=(const basic_socket_ext&) BOOST_ASIO_DELETED;
1808 
1809   struct initiate_async_connect
1810   {
1811     template <typename ConnectHandler>
operator ()boost::asio::basic_socket_ext::initiate_async_connect1812     void operator()(BOOST_ASIO_MOVE_ARG(ConnectHandler) handler,
1813         basic_socket_ext* self, const endpoint_type& peer_endpoint,
1814         const boost::system::error_code& open_ec) const
1815     {
1816       // If you get an error on the following line it means that your handler
1817       // does not meet the documented type requirements for a ConnectHandler.
1818       BOOST_ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check;
1819 
1820       if (open_ec)
1821       {
1822           boost::asio::post(self->impl_.get_executor(),
1823               boost::asio::detail::bind_handler(
1824                 BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler), open_ec));
1825       }
1826       else
1827       {
1828         detail::non_const_lvalue<ConnectHandler> handler2(handler);
1829         self->impl_.get_service().async_connect(
1830             self->impl_.get_implementation(), peer_endpoint,
1831             handler2.value, self->impl_.get_implementation_executor());
1832       }
1833     }
1834   };
1835 
1836   struct initiate_async_wait
1837   {
1838     template <typename WaitHandler>
operator ()boost::asio::basic_socket_ext::initiate_async_wait1839     void operator()(BOOST_ASIO_MOVE_ARG(WaitHandler) handler,
1840         basic_socket_ext* self, wait_type w) const
1841     {
1842       // If you get an error on the following line it means that your handler
1843       // does not meet the documented type requirements for a WaitHandler.
1844       BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
1845 
1846       detail::non_const_lvalue<WaitHandler> handler2(handler);
1847       self->impl_.get_service().async_wait(
1848           self->impl_.get_implementation(), w, handler2.value,
1849           self->impl_.get_implementation_executor());
1850     }
1851   };
1852 };
1853 
1854 } // namespace asio
1855 } // namespace boost
1856 
1857 #include <boost/asio/detail/pop_options.hpp>
1858 
1859 #endif // BOOST_ASIO_BASIC_SOCKET_EXT_HPP
1860