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