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