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