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