10ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
20ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// basic_socket.hpp
30ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// ~~~~~~~~~~~~~~~~
40ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
50ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
60ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
70ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// Distributed under the Boost Software License, Version 1.0. (See accompanying
80ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
90ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#ifndef ASIO_BASIC_SOCKET_HPP
120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#define ASIO_BASIC_SOCKET_HPP
130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/config.hpp"
160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/async_result.hpp"
170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/basic_io_object.hpp"
180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/handler_type_requirements.hpp"
190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/throw_error.hpp"
200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/type_traits.hpp"
210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/error.hpp"
220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/socket_base.hpp"
230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/push_options.hpp"
250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffienamespace asio {
270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie/// Provides socket functionality.
290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie/**
300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie * The basic_socket class template provides functionality that is common to both
310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie * stream-oriented and datagram-oriented sockets.
320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie *
330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie * @par Thread Safety
340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie * @e Distinct @e objects: Safe.@n
350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie * @e Shared @e objects: Unsafe.
360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie */
370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffietemplate <typename Protocol, typename SocketService>
380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieclass basic_socket
390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  : public basic_io_object<SocketService>,
400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    public socket_base
410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffiepublic:
430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// (Deprecated: Use native_handle_type.) The native representation of a
440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// socket.
450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  typedef typename SocketService::native_handle_type native_type;
460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// The native representation of a socket.
480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  typedef typename SocketService::native_handle_type native_handle_type;
490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// The protocol type.
510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  typedef Protocol protocol_type;
520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// The endpoint type.
540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  typedef typename Protocol::endpoint endpoint_type;
550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// A basic_socket is always the lowest layer.
570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  typedef basic_socket<Protocol, SocketService> lowest_layer_type;
580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Construct a basic_socket without opening it.
600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This constructor creates a socket without opening it.
620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param io_service The io_service object that the socket will use to
640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * dispatch handlers for any asynchronous operations performed on the socket.
650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  explicit basic_socket(asio::io_service& io_service)
670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    : basic_io_object<SocketService>(io_service)
680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Construct and open a basic_socket.
720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This constructor creates and opens a socket.
740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param io_service The io_service object that the socket will use to
760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * dispatch handlers for any asynchronous operations performed on the socket.
770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param protocol An object specifying protocol parameters to be used.
790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @throws asio::system_error Thrown on failure.
810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  basic_socket(asio::io_service& io_service,
830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      const protocol_type& protocol)
840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    : basic_io_object<SocketService>(io_service)
850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::error_code ec;
870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    this->get_service().open(this->get_implementation(), protocol, ec);
880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::detail::throw_error(ec, "open");
890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Construct a basic_socket, opening it and binding it to the given local
920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// endpoint.
930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This constructor creates a socket and automatically opens it bound to the
950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * specified endpoint on the local machine. The protocol used is the protocol
960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * associated with the given endpoint.
970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param io_service The io_service object that the socket will use to
990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * dispatch handlers for any asynchronous operations performed on the socket.
1000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
1010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param endpoint An endpoint on the local machine to which the socket will
1020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * be bound.
1030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
1040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @throws asio::system_error Thrown on failure.
1050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
1060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  basic_socket(asio::io_service& io_service,
1070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      const endpoint_type& endpoint)
1080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    : basic_io_object<SocketService>(io_service)
1090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
1100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::error_code ec;
1110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    const protocol_type protocol = endpoint.protocol();
1120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    this->get_service().open(this->get_implementation(), protocol, ec);
1130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::detail::throw_error(ec, "open");
1140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    this->get_service().bind(this->get_implementation(), endpoint, ec);
1150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::detail::throw_error(ec, "bind");
1160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
1170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Construct a basic_socket on an existing native socket.
1190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
1200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This constructor creates a socket object to hold an existing native socket.
1210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
1220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param io_service The io_service object that the socket will use to
1230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * dispatch handlers for any asynchronous operations performed on the socket.
1240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
1250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param protocol An object specifying protocol parameters to be used.
1260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
1270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param native_socket A native socket.
1280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
1290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @throws asio::system_error Thrown on failure.
1300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
1310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  basic_socket(asio::io_service& io_service,
1320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      const protocol_type& protocol, const native_handle_type& native_socket)
1330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    : basic_io_object<SocketService>(io_service)
1340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
1350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::error_code ec;
1360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    this->get_service().assign(this->get_implementation(),
1370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        protocol, native_socket, ec);
1380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::detail::throw_error(ec, "assign");
1390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
1400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Move-construct a basic_socket from another.
1420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
1430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This constructor moves a socket from one object to another.
1440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
1450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param other The other basic_socket object from which the move will
1460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * occur.
1470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
1480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @note Following the move, the moved-from object is in the same state as if
1490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * constructed using the @c basic_socket(io_service&) constructor.
1500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
1510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  basic_socket(basic_socket&& other)
1520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    : basic_io_object<SocketService>(
1530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        ASIO_MOVE_CAST(basic_socket)(other))
1540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
1550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
1560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Move-assign a basic_socket from another.
1580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
1590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This assignment operator moves a socket from one object to another.
1600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
1610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param other The other basic_socket object from which the move will
1620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * occur.
1630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
1640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @note Following the move, the moved-from object is in the same state as if
1650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * constructed using the @c basic_socket(io_service&) constructor.
1660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
1670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  basic_socket& operator=(basic_socket&& other)
1680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
1690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    basic_io_object<SocketService>::operator=(
1700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        ASIO_MOVE_CAST(basic_socket)(other));
1710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return *this;
1720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
1730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  // All sockets have access to each other's implementations.
1750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename Protocol1, typename SocketService1>
1760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  friend class basic_socket;
1770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Move-construct a basic_socket from a socket of another protocol type.
1790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
1800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This constructor moves a socket from one object to another.
1810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
1820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param other The other basic_socket object from which the move will
1830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * occur.
1840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
1850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @note Following the move, the moved-from object is in the same state as if
1860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * constructed using the @c basic_socket(io_service&) constructor.
1870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
1880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename Protocol1, typename SocketService1>
1890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  basic_socket(basic_socket<Protocol1, SocketService1>&& other,
1900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
1910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    : basic_io_object<SocketService>(other.get_io_service())
1920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
1930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    this->get_service().template converting_move_construct<Protocol1>(
1940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        this->get_implementation(), other.get_implementation());
1950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
1960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Move-assign a basic_socket from a socket of another protocol type.
1980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
1990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This assignment operator moves a socket from one object to another.
2000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
2010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param other The other basic_socket object from which the move will
2020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * occur.
2030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
2040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @note Following the move, the moved-from object is in the same state as if
2050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * constructed using the @c basic_socket(io_service&) constructor.
2060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
2070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename Protocol1, typename SocketService1>
2080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  typename enable_if<is_convertible<Protocol1, Protocol>::value,
2090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      basic_socket>::type& operator=(
2100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        basic_socket<Protocol1, SocketService1>&& other)
2110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
2120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    basic_socket tmp(ASIO_MOVE_CAST2(basic_socket<
2130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie            Protocol1, SocketService1>)(other));
2140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    basic_io_object<SocketService>::operator=(
2150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        ASIO_MOVE_CAST(basic_socket)(tmp));
2160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return *this;
2170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
2180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Get a reference to the lowest layer.
2200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
2210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function returns a reference to the lowest layer in a stack of
2220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * layers. Since a basic_socket cannot contain any further layers, it simply
2230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * returns a reference to itself.
2240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
2250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @return A reference to the lowest layer in the stack of layers. Ownership
2260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * is not transferred to the caller.
2270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
2280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  lowest_layer_type& lowest_layer()
2290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
2300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return *this;
2310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
2320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Get a const reference to the lowest layer.
2340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
2350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function returns a const reference to the lowest layer in a stack of
2360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * layers. Since a basic_socket cannot contain any further layers, it simply
2370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * returns a reference to itself.
2380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
2390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @return A const reference to the lowest layer in the stack of layers.
2400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * Ownership is not transferred to the caller.
2410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
2420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  const lowest_layer_type& lowest_layer() const
2430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
2440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return *this;
2450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
2460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Open the socket using the specified protocol.
2480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
2490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function opens the socket so that it will use the specified protocol.
2500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
2510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param protocol An object specifying protocol parameters to be used.
2520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
2530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @throws asio::system_error Thrown on failure.
2540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
2550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @par Example
2560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @code
2570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::socket socket(io_service);
2580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * socket.open(asio::ip::tcp::v4());
2590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @endcode
2600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
2610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  void open(const protocol_type& protocol = protocol_type())
2620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
2630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::error_code ec;
2640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    this->get_service().open(this->get_implementation(), protocol, ec);
2650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::detail::throw_error(ec, "open");
2660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
2670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Open the socket using the specified protocol.
2690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
2700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function opens the socket so that it will use the specified protocol.
2710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
2720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param protocol An object specifying which protocol is to be used.
2730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
2740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param ec Set to indicate what error occurred, if any.
2750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
2760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @par Example
2770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @code
2780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::socket socket(io_service);
2790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::error_code ec;
2800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * socket.open(asio::ip::tcp::v4(), ec);
2810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * if (ec)
2820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * {
2830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   // An error occurred.
2840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * }
2850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @endcode
2860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
2870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  asio::error_code open(const protocol_type& protocol,
2880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      asio::error_code& ec)
2890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
2900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return this->get_service().open(this->get_implementation(), protocol, ec);
2910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
2920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Assign an existing native socket to the socket.
2940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /*
2950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function opens the socket to hold an existing native socket.
2960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
2970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param protocol An object specifying which protocol is to be used.
2980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
2990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param native_socket A native socket.
3000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
3010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @throws asio::system_error Thrown on failure.
3020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
3030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  void assign(const protocol_type& protocol,
3040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      const native_handle_type& native_socket)
3050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
3060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::error_code ec;
3070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    this->get_service().assign(this->get_implementation(),
3080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        protocol, native_socket, ec);
3090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::detail::throw_error(ec, "assign");
3100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
3110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
3120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Assign an existing native socket to the socket.
3130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /*
3140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function opens the socket to hold an existing native socket.
3150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
3160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param protocol An object specifying which protocol is to be used.
3170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
3180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param native_socket A native socket.
3190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
3200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param ec Set to indicate what error occurred, if any.
3210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
3220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  asio::error_code assign(const protocol_type& protocol,
3230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      const native_handle_type& native_socket, asio::error_code& ec)
3240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
3250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return this->get_service().assign(this->get_implementation(),
3260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        protocol, native_socket, ec);
3270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
3280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
3290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Determine whether the socket is open.
3300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  bool is_open() const
3310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
3320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return this->get_service().is_open(this->get_implementation());
3330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
3340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
3350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Close the socket.
3360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
3370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is used to close the socket. Any asynchronous send, receive
3380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * or connect operations will be cancelled immediately, and will complete
3390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * with the asio::error::operation_aborted error.
3400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
3410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @throws asio::system_error Thrown on failure. Note that, even if
3420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * the function indicates an error, the underlying descriptor is closed.
3430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
3440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @note For portable behaviour with respect to graceful closure of a
3450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * connected socket, call shutdown() before closing the socket.
3460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
3470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  void close()
3480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
3490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::error_code ec;
3500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    this->get_service().close(this->get_implementation(), ec);
3510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::detail::throw_error(ec, "close");
3520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
3530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
3540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Close the socket.
3550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
3560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is used to close the socket. Any asynchronous send, receive
3570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * or connect operations will be cancelled immediately, and will complete
3580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * with the asio::error::operation_aborted error.
3590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
3600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param ec Set to indicate what error occurred, if any. Note that, even if
3610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * the function indicates an error, the underlying descriptor is closed.
3620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
3630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @par Example
3640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @code
3650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::socket socket(io_service);
3660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * ...
3670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::error_code ec;
3680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * socket.close(ec);
3690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * if (ec)
3700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * {
3710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   // An error occurred.
3720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * }
3730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @endcode
3740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
3750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @note For portable behaviour with respect to graceful closure of a
3760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * connected socket, call shutdown() before closing the socket.
3770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
3780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  asio::error_code close(asio::error_code& ec)
3790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
3800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return this->get_service().close(this->get_implementation(), ec);
3810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
3820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
3830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// (Deprecated: Use native_handle().) Get the native socket representation.
3840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
3850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function may be used to obtain the underlying representation of the
3860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * socket. This is intended to allow access to native socket functionality
3870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * that is not otherwise provided.
3880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
3890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  native_type native()
3900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
3910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return this->get_service().native_handle(this->get_implementation());
3920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
3930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
3940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Get the native socket representation.
3950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
3960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function may be used to obtain the underlying representation of the
3970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * socket. This is intended to allow access to native socket functionality
3980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * that is not otherwise provided.
3990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
4000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  native_handle_type native_handle()
4010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
4020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return this->get_service().native_handle(this->get_implementation());
4030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
4040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Cancel all asynchronous operations associated with the socket.
4060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
4070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function causes all outstanding asynchronous connect, send and receive
4080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * operations to finish immediately, and the handlers for cancelled operations
4090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * will be passed the asio::error::operation_aborted error.
4100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
4110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @throws asio::system_error Thrown on failure.
4120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
4130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @note Calls to cancel() will always fail with
4140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::error::operation_not_supported when run on Windows XP, Windows
4150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * Server 2003, and earlier versions of Windows, unless
4160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has
4170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * two issues that should be considered before enabling its use:
4180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
4190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @li It will only cancel asynchronous operations that were initiated in the
4200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * current thread.
4210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
4220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @li It can appear to complete without error, but the request to cancel the
4230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * unfinished operations may be silently ignored by the operating system.
4240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * Whether it works or not seems to depend on the drivers that are installed.
4250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
4260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * For portable cancellation, consider using one of the following
4270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * alternatives:
4280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
4290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @li Disable asio's I/O completion port backend by defining
4300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * ASIO_DISABLE_IOCP.
4310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
4320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @li Use the close() function to simultaneously cancel the outstanding
4330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * operations and close the socket.
4340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
4350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * When running on Windows Vista, Windows Server 2008, and later, the
4360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * CancelIoEx function is always used. This function does not have the
4370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * problems described above.
4380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
4390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  void cancel()
4400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
4410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::error_code ec;
4420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    this->get_service().cancel(this->get_implementation(), ec);
4430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::detail::throw_error(ec, "cancel");
4440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
4450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Cancel all asynchronous operations associated with the socket.
4470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
4480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function causes all outstanding asynchronous connect, send and receive
4490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * operations to finish immediately, and the handlers for cancelled operations
4500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * will be passed the asio::error::operation_aborted error.
4510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
4520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param ec Set to indicate what error occurred, if any.
4530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
4540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @note Calls to cancel() will always fail with
4550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::error::operation_not_supported when run on Windows XP, Windows
4560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * Server 2003, and earlier versions of Windows, unless
4570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has
4580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * two issues that should be considered before enabling its use:
4590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
4600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @li It will only cancel asynchronous operations that were initiated in the
4610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * current thread.
4620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
4630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @li It can appear to complete without error, but the request to cancel the
4640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * unfinished operations may be silently ignored by the operating system.
4650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * Whether it works or not seems to depend on the drivers that are installed.
4660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
4670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * For portable cancellation, consider using one of the following
4680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * alternatives:
4690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
4700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @li Disable asio's I/O completion port backend by defining
4710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * ASIO_DISABLE_IOCP.
4720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
4730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @li Use the close() function to simultaneously cancel the outstanding
4740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * operations and close the socket.
4750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
4760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * When running on Windows Vista, Windows Server 2008, and later, the
4770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * CancelIoEx function is always used. This function does not have the
4780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * problems described above.
4790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
4800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  asio::error_code cancel(asio::error_code& ec)
4810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
4820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return this->get_service().cancel(this->get_implementation(), ec);
4830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
4840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Determine whether the socket is at the out-of-band data mark.
4860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
4870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is used to check whether the socket input is currently
4880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * positioned at the out-of-band data mark.
4890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
4900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @return A bool indicating whether the socket is at the out-of-band data
4910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * mark.
4920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
4930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @throws asio::system_error Thrown on failure.
4940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
4950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  bool at_mark() const
4960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
4970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::error_code ec;
4980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    bool b = this->get_service().at_mark(this->get_implementation(), ec);
4990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::detail::throw_error(ec, "at_mark");
5000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return b;
5010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
5020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
5030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Determine whether the socket is at the out-of-band data mark.
5040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
5050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is used to check whether the socket input is currently
5060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * positioned at the out-of-band data mark.
5070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
5080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param ec Set to indicate what error occurred, if any.
5090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
5100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @return A bool indicating whether the socket is at the out-of-band data
5110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * mark.
5120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
5130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  bool at_mark(asio::error_code& ec) const
5140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
5150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return this->get_service().at_mark(this->get_implementation(), ec);
5160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
5170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
5180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Determine the number of bytes available for reading.
5190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
5200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is used to determine the number of bytes that may be read
5210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * without blocking.
5220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
5230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @return The number of bytes that may be read without blocking, or 0 if an
5240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * error occurs.
5250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
5260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @throws asio::system_error Thrown on failure.
5270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
5280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  std::size_t available() const
5290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
5300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::error_code ec;
5310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    std::size_t s = this->get_service().available(
5320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        this->get_implementation(), ec);
5330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::detail::throw_error(ec, "available");
5340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return s;
5350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
5360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
5370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Determine the number of bytes available for reading.
5380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
5390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is used to determine the number of bytes that may be read
5400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * without blocking.
5410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
5420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param ec Set to indicate what error occurred, if any.
5430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
5440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @return The number of bytes that may be read without blocking, or 0 if an
5450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * error occurs.
5460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
5470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  std::size_t available(asio::error_code& ec) const
5480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
5490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return this->get_service().available(this->get_implementation(), ec);
5500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
5510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
5520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Bind the socket to the given local endpoint.
5530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
5540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function binds the socket to the specified endpoint on the local
5550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * machine.
5560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
5570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param endpoint An endpoint on the local machine to which the socket will
5580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * be bound.
5590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
5600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @throws asio::system_error Thrown on failure.
5610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
5620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @par Example
5630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @code
5640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::socket socket(io_service);
5650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * socket.open(asio::ip::tcp::v4());
5660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * socket.bind(asio::ip::tcp::endpoint(
5670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *       asio::ip::tcp::v4(), 12345));
5680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @endcode
5690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
5700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  void bind(const endpoint_type& endpoint)
5710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
5720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::error_code ec;
5730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    this->get_service().bind(this->get_implementation(), endpoint, ec);
5740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::detail::throw_error(ec, "bind");
5750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
5760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
5770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Bind the socket to the given local endpoint.
5780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
5790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function binds the socket to the specified endpoint on the local
5800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * machine.
5810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
5820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param endpoint An endpoint on the local machine to which the socket will
5830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * be bound.
5840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
5850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param ec Set to indicate what error occurred, if any.
5860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
5870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @par Example
5880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @code
5890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::socket socket(io_service);
5900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * socket.open(asio::ip::tcp::v4());
5910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::error_code ec;
5920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * socket.bind(asio::ip::tcp::endpoint(
5930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *       asio::ip::tcp::v4(), 12345), ec);
5940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * if (ec)
5950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * {
5960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   // An error occurred.
5970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * }
5980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @endcode
5990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
6000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  asio::error_code bind(const endpoint_type& endpoint,
6010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      asio::error_code& ec)
6020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
6030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return this->get_service().bind(this->get_implementation(), endpoint, ec);
6040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
6050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
6060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Connect the socket to the specified endpoint.
6070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
6080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is used to connect a socket to the specified remote endpoint.
6090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * The function call will block until the connection is successfully made or
6100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * an error occurs.
6110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
6120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * The socket is automatically opened if it is not already open. If the
6130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * connect fails, and the socket was automatically opened, the socket is
6140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * not returned to the closed state.
6150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
6160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param peer_endpoint The remote endpoint to which the socket will be
6170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * connected.
6180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
6190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @throws asio::system_error Thrown on failure.
6200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
6210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @par Example
6220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @code
6230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::socket socket(io_service);
6240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::endpoint endpoint(
6250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *     asio::ip::address::from_string("1.2.3.4"), 12345);
6260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * socket.connect(endpoint);
6270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @endcode
6280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
6290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  void connect(const endpoint_type& peer_endpoint)
6300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
6310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::error_code ec;
6320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    if (!is_open())
6330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
6340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      this->get_service().open(this->get_implementation(),
6350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          peer_endpoint.protocol(), ec);
6360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      asio::detail::throw_error(ec, "connect");
6370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
6380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    this->get_service().connect(this->get_implementation(), peer_endpoint, ec);
6390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::detail::throw_error(ec, "connect");
6400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
6410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
6420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Connect the socket to the specified endpoint.
6430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
6440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is used to connect a socket to the specified remote endpoint.
6450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * The function call will block until the connection is successfully made or
6460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * an error occurs.
6470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
6480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * The socket is automatically opened if it is not already open. If the
6490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * connect fails, and the socket was automatically opened, the socket is
6500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * not returned to the closed state.
6510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
6520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param peer_endpoint The remote endpoint to which the socket will be
6530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * connected.
6540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
6550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param ec Set to indicate what error occurred, if any.
6560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
6570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @par Example
6580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @code
6590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::socket socket(io_service);
6600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::endpoint endpoint(
6610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *     asio::ip::address::from_string("1.2.3.4"), 12345);
6620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::error_code ec;
6630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * socket.connect(endpoint, ec);
6640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * if (ec)
6650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * {
6660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   // An error occurred.
6670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * }
6680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @endcode
6690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
6700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  asio::error_code connect(const endpoint_type& peer_endpoint,
6710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      asio::error_code& ec)
6720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
6730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    if (!is_open())
6740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
6750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      if (this->get_service().open(this->get_implementation(),
6760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie            peer_endpoint.protocol(), ec))
6770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      {
6780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        return ec;
6790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      }
6800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
6810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
6820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return this->get_service().connect(
6830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        this->get_implementation(), peer_endpoint, ec);
6840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
6850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
6860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Start an asynchronous connect.
6870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
6880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is used to asynchronously connect a socket to the specified
6890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * remote endpoint. The function call always returns immediately.
6900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
6910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * The socket is automatically opened if it is not already open. If the
6920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * connect fails, and the socket was automatically opened, the socket is
6930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * not returned to the closed state.
6940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
6950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param peer_endpoint The remote endpoint to which the socket will be
6960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * connected. Copies will be made of the endpoint object as required.
6970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
6980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param handler The handler to be called when the connection operation
6990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * completes. Copies will be made of the handler as required. The function
7000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * signature of the handler must be:
7010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @code void handler(
7020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   const asio::error_code& error // Result of operation
7030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * ); @endcode
7040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * Regardless of whether the asynchronous operation completes immediately or
7050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * not, the handler will not be invoked from within this function. Invocation
7060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * of the handler will be performed in a manner equivalent to using
7070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::io_service::post().
7080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
7090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @par Example
7100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @code
7110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * void connect_handler(const asio::error_code& error)
7120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * {
7130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   if (!error)
7140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   {
7150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *     // Connect succeeded.
7160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   }
7170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * }
7180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
7190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * ...
7200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
7210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::socket socket(io_service);
7220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::endpoint endpoint(
7230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *     asio::ip::address::from_string("1.2.3.4"), 12345);
7240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * socket.async_connect(endpoint, connect_handler);
7250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @endcode
7260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
7270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename ConnectHandler>
7280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  ASIO_INITFN_RESULT_TYPE(ConnectHandler,
7290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      void (asio::error_code))
7300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  async_connect(const endpoint_type& peer_endpoint,
7310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      ASIO_MOVE_ARG(ConnectHandler) handler)
7320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
7330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    // If you get an error on the following line it means that your handler does
7340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    // not meet the documented type requirements for a ConnectHandler.
7350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check;
7360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
7370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    if (!is_open())
7380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
7390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      asio::error_code ec;
7400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      const protocol_type protocol = peer_endpoint.protocol();
7410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      if (this->get_service().open(this->get_implementation(), protocol, ec))
7420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      {
7430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        detail::async_result_init<
7440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          ConnectHandler, void (asio::error_code)> init(
7450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie            ASIO_MOVE_CAST(ConnectHandler)(handler));
7460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
7470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        this->get_io_service().post(
7480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie            asio::detail::bind_handler(
7490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(
7500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie                ConnectHandler, void (asio::error_code)))(
7510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie                  init.handler), ec));
7520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
7530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        return init.result.get();
7540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      }
7550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
7560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
7570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return this->get_service().async_connect(this->get_implementation(),
7580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        peer_endpoint, ASIO_MOVE_CAST(ConnectHandler)(handler));
7590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
7600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
7610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Set an option on the socket.
7620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
7630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is used to set an option on the socket.
7640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
7650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param option The new option value to be set on the socket.
7660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
7670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @throws asio::system_error Thrown on failure.
7680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
7690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @sa SettableSocketOption @n
7700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::broadcast @n
7710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::do_not_route @n
7720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::keep_alive @n
7730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::linger @n
7740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::receive_buffer_size @n
7750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::receive_low_watermark @n
7760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::reuse_address @n
7770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::send_buffer_size @n
7780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::send_low_watermark @n
7790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::multicast::join_group @n
7800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::multicast::leave_group @n
7810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::multicast::enable_loopback @n
7820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::multicast::outbound_interface @n
7830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::multicast::hops @n
7840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::no_delay
7850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
7860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @par Example
7870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * Setting the IPPROTO_TCP/TCP_NODELAY option:
7880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @code
7890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::socket socket(io_service);
7900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * ...
7910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::no_delay option(true);
7920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * socket.set_option(option);
7930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @endcode
7940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
7950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename SettableSocketOption>
7960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  void set_option(const SettableSocketOption& option)
7970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
7980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::error_code ec;
7990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    this->get_service().set_option(this->get_implementation(), option, ec);
8000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::detail::throw_error(ec, "set_option");
8010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
8020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
8030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Set an option on the socket.
8040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
8050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is used to set an option on the socket.
8060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
8070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param option The new option value to be set on the socket.
8080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
8090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param ec Set to indicate what error occurred, if any.
8100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
8110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @sa SettableSocketOption @n
8120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::broadcast @n
8130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::do_not_route @n
8140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::keep_alive @n
8150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::linger @n
8160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::receive_buffer_size @n
8170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::receive_low_watermark @n
8180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::reuse_address @n
8190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::send_buffer_size @n
8200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::send_low_watermark @n
8210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::multicast::join_group @n
8220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::multicast::leave_group @n
8230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::multicast::enable_loopback @n
8240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::multicast::outbound_interface @n
8250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::multicast::hops @n
8260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::no_delay
8270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
8280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @par Example
8290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * Setting the IPPROTO_TCP/TCP_NODELAY option:
8300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @code
8310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::socket socket(io_service);
8320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * ...
8330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::no_delay option(true);
8340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::error_code ec;
8350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * socket.set_option(option, ec);
8360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * if (ec)
8370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * {
8380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   // An error occurred.
8390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * }
8400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @endcode
8410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
8420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename SettableSocketOption>
8430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  asio::error_code set_option(const SettableSocketOption& option,
8440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      asio::error_code& ec)
8450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
8460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return this->get_service().set_option(
8470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        this->get_implementation(), option, ec);
8480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
8490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
8500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Get an option from the socket.
8510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
8520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is used to get the current value of an option on the socket.
8530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
8540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param option The option value to be obtained from the socket.
8550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
8560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @throws asio::system_error Thrown on failure.
8570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
8580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @sa GettableSocketOption @n
8590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::broadcast @n
8600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::do_not_route @n
8610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::keep_alive @n
8620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::linger @n
8630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::receive_buffer_size @n
8640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::receive_low_watermark @n
8650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::reuse_address @n
8660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::send_buffer_size @n
8670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::send_low_watermark @n
8680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::multicast::join_group @n
8690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::multicast::leave_group @n
8700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::multicast::enable_loopback @n
8710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::multicast::outbound_interface @n
8720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::multicast::hops @n
8730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::no_delay
8740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
8750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @par Example
8760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:
8770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @code
8780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::socket socket(io_service);
8790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * ...
8800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::socket::keep_alive option;
8810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * socket.get_option(option);
8820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * bool is_set = option.value();
8830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @endcode
8840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
8850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename GettableSocketOption>
8860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  void get_option(GettableSocketOption& option) const
8870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
8880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::error_code ec;
8890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    this->get_service().get_option(this->get_implementation(), option, ec);
8900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::detail::throw_error(ec, "get_option");
8910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
8920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
8930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Get an option from the socket.
8940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
8950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is used to get the current value of an option on the socket.
8960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
8970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param option The option value to be obtained from the socket.
8980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
8990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param ec Set to indicate what error occurred, if any.
9000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
9010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @sa GettableSocketOption @n
9020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::broadcast @n
9030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::do_not_route @n
9040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::keep_alive @n
9050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::linger @n
9060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::receive_buffer_size @n
9070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::receive_low_watermark @n
9080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::reuse_address @n
9090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::send_buffer_size @n
9100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::send_low_watermark @n
9110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::multicast::join_group @n
9120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::multicast::leave_group @n
9130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::multicast::enable_loopback @n
9140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::multicast::outbound_interface @n
9150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::multicast::hops @n
9160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::no_delay
9170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
9180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @par Example
9190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:
9200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @code
9210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::socket socket(io_service);
9220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * ...
9230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::socket::keep_alive option;
9240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::error_code ec;
9250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * socket.get_option(option, ec);
9260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * if (ec)
9270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * {
9280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   // An error occurred.
9290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * }
9300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * bool is_set = option.value();
9310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @endcode
9320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
9330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename GettableSocketOption>
9340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  asio::error_code get_option(GettableSocketOption& option,
9350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      asio::error_code& ec) const
9360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
9370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return this->get_service().get_option(
9380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        this->get_implementation(), option, ec);
9390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
9400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
9410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Perform an IO control command on the socket.
9420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
9430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is used to execute an IO control command on the socket.
9440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
9450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param command The IO control command to be performed on the socket.
9460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
9470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @throws asio::system_error Thrown on failure.
9480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
9490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @sa IoControlCommand @n
9500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::bytes_readable @n
9510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::non_blocking_io
9520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
9530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @par Example
9540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * Getting the number of bytes ready to read:
9550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @code
9560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::socket socket(io_service);
9570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * ...
9580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::socket::bytes_readable command;
9590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * socket.io_control(command);
9600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * std::size_t bytes_readable = command.get();
9610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @endcode
9620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
9630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename IoControlCommand>
9640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  void io_control(IoControlCommand& command)
9650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
9660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::error_code ec;
9670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    this->get_service().io_control(this->get_implementation(), command, ec);
9680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::detail::throw_error(ec, "io_control");
9690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
9700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
9710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Perform an IO control command on the socket.
9720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
9730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is used to execute an IO control command on the socket.
9740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
9750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param command The IO control command to be performed on the socket.
9760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
9770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param ec Set to indicate what error occurred, if any.
9780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
9790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @sa IoControlCommand @n
9800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::bytes_readable @n
9810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::socket_base::non_blocking_io
9820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
9830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @par Example
9840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * Getting the number of bytes ready to read:
9850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @code
9860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::socket socket(io_service);
9870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * ...
9880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::socket::bytes_readable command;
9890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::error_code ec;
9900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * socket.io_control(command, ec);
9910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * if (ec)
9920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * {
9930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   // An error occurred.
9940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * }
9950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * std::size_t bytes_readable = command.get();
9960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @endcode
9970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
9980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename IoControlCommand>
9990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  asio::error_code io_control(IoControlCommand& command,
10000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      asio::error_code& ec)
10010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
10020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return this->get_service().io_control(
10030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        this->get_implementation(), command, ec);
10040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
10050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
10060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Gets the non-blocking mode of the socket.
10070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
10080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @returns @c true if the socket's synchronous operations will fail with
10090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::error::would_block if they are unable to perform the requested
10100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * operation immediately. If @c false, synchronous operations will block
10110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * until complete.
10120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
10130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @note The non-blocking mode has no effect on the behaviour of asynchronous
10140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * operations. Asynchronous operations will never fail with the error
10150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::error::would_block.
10160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
10170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  bool non_blocking() const
10180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
10190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return this->get_service().non_blocking(this->get_implementation());
10200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
10210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
10220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Sets the non-blocking mode of the socket.
10230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
10240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param mode If @c true, the socket's synchronous operations will fail with
10250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::error::would_block if they are unable to perform the requested
10260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * operation immediately. If @c false, synchronous operations will block
10270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * until complete.
10280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
10290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @throws asio::system_error Thrown on failure.
10300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
10310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @note The non-blocking mode has no effect on the behaviour of asynchronous
10320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * operations. Asynchronous operations will never fail with the error
10330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::error::would_block.
10340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
10350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  void non_blocking(bool mode)
10360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
10370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::error_code ec;
10380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    this->get_service().non_blocking(this->get_implementation(), mode, ec);
10390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::detail::throw_error(ec, "non_blocking");
10400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
10410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
10420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Sets the non-blocking mode of the socket.
10430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
10440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param mode If @c true, the socket's synchronous operations will fail with
10450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::error::would_block if they are unable to perform the requested
10460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * operation immediately. If @c false, synchronous operations will block
10470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * until complete.
10480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
10490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param ec Set to indicate what error occurred, if any.
10500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
10510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @note The non-blocking mode has no effect on the behaviour of asynchronous
10520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * operations. Asynchronous operations will never fail with the error
10530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::error::would_block.
10540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
10550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  asio::error_code non_blocking(
10560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      bool mode, asio::error_code& ec)
10570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
10580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return this->get_service().non_blocking(
10590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        this->get_implementation(), mode, ec);
10600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
10610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
10620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Gets the non-blocking mode of the native socket implementation.
10630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
10640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is used to retrieve the non-blocking mode of the underlying
10650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * native socket. This mode has no effect on the behaviour of the socket
10660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * object's synchronous operations.
10670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
10680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @returns @c true if the underlying socket is in non-blocking mode and
10690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * direct system calls may fail with asio::error::would_block (or the
10700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * equivalent system error).
10710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
10720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @note The current non-blocking mode is cached by the socket object.
10730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * Consequently, the return value may be incorrect if the non-blocking mode
10740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * was set directly on the native socket.
10750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
10760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @par Example
10770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is intended to allow the encapsulation of arbitrary
10780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * non-blocking system calls as asynchronous operations, in a way that is
10790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * transparent to the user of the socket object. The following example
10800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * illustrates how Linux's @c sendfile system call might be encapsulated:
10810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @code template <typename Handler>
10820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * struct sendfile_op
10830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * {
10840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   tcp::socket& sock_;
10850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   int fd_;
10860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   Handler handler_;
10870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   off_t offset_;
10880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   std::size_t total_bytes_transferred_;
10890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
10900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   // Function call operator meeting WriteHandler requirements.
10910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   // Used as the handler for the async_write_some operation.
10920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   void operator()(asio::error_code ec, std::size_t)
10930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   {
10940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *     // Put the underlying socket into non-blocking mode.
10950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *     if (!ec)
10960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *       if (!sock_.native_non_blocking())
10970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         sock_.native_non_blocking(true, ec);
10980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
10990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *     if (!ec)
11000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *     {
11010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *       for (;;)
11020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *       {
11030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         // Try the system call.
11040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         errno = 0;
11050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);
11060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         ec = asio::error_code(n < 0 ? errno : 0,
11070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *             asio::error::get_system_category());
11080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         total_bytes_transferred_ += ec ? 0 : n;
11090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
11100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         // Retry operation immediately if interrupted by signal.
11110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         if (ec == asio::error::interrupted)
11120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *           continue;
11130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
11140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         // Check if we need to run the operation again.
11150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         if (ec == asio::error::would_block
11160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *             || ec == asio::error::try_again)
11170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         {
11180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *           // We have to wait for the socket to become ready again.
11190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *           sock_.async_write_some(asio::null_buffers(), *this);
11200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *           return;
11210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         }
11220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
11230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         if (ec || n == 0)
11240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         {
11250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *           // An error occurred, or we have reached the end of the file.
11260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *           // Either way we must exit the loop so we can call the handler.
11270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *           break;
11280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         }
11290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
11300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         // Loop around to try calling sendfile again.
11310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *       }
11320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *     }
11330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
11340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *     // Pass result back to user's handler.
11350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *     handler_(ec, total_bytes_transferred_);
11360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   }
11370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * };
11380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
11390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * template <typename Handler>
11400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * void async_sendfile(tcp::socket& sock, int fd, Handler h)
11410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * {
11420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
11430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   sock.async_write_some(asio::null_buffers(), op);
11440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * } @endcode
11450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
11460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  bool native_non_blocking() const
11470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
11480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return this->get_service().native_non_blocking(this->get_implementation());
11490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
11500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
11510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Sets the non-blocking mode of the native socket implementation.
11520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
11530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is used to modify the non-blocking mode of the underlying
11540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * native socket. It has no effect on the behaviour of the socket object's
11550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * synchronous operations.
11560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
11570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param mode If @c true, the underlying socket is put into non-blocking
11580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * mode and direct system calls may fail with asio::error::would_block
11590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * (or the equivalent system error).
11600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
11610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @throws asio::system_error Thrown on failure. If the @c mode is
11620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @c false, but the current value of @c non_blocking() is @c true, this
11630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * function fails with asio::error::invalid_argument, as the
11640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * combination does not make sense.
11650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
11660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @par Example
11670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is intended to allow the encapsulation of arbitrary
11680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * non-blocking system calls as asynchronous operations, in a way that is
11690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * transparent to the user of the socket object. The following example
11700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * illustrates how Linux's @c sendfile system call might be encapsulated:
11710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @code template <typename Handler>
11720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * struct sendfile_op
11730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * {
11740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   tcp::socket& sock_;
11750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   int fd_;
11760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   Handler handler_;
11770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   off_t offset_;
11780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   std::size_t total_bytes_transferred_;
11790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
11800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   // Function call operator meeting WriteHandler requirements.
11810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   // Used as the handler for the async_write_some operation.
11820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   void operator()(asio::error_code ec, std::size_t)
11830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   {
11840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *     // Put the underlying socket into non-blocking mode.
11850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *     if (!ec)
11860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *       if (!sock_.native_non_blocking())
11870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         sock_.native_non_blocking(true, ec);
11880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
11890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *     if (!ec)
11900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *     {
11910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *       for (;;)
11920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *       {
11930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         // Try the system call.
11940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         errno = 0;
11950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);
11960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         ec = asio::error_code(n < 0 ? errno : 0,
11970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *             asio::error::get_system_category());
11980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         total_bytes_transferred_ += ec ? 0 : n;
11990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
12000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         // Retry operation immediately if interrupted by signal.
12010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         if (ec == asio::error::interrupted)
12020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *           continue;
12030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
12040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         // Check if we need to run the operation again.
12050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         if (ec == asio::error::would_block
12060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *             || ec == asio::error::try_again)
12070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         {
12080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *           // We have to wait for the socket to become ready again.
12090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *           sock_.async_write_some(asio::null_buffers(), *this);
12100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *           return;
12110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         }
12120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
12130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         if (ec || n == 0)
12140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         {
12150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *           // An error occurred, or we have reached the end of the file.
12160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *           // Either way we must exit the loop so we can call the handler.
12170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *           break;
12180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         }
12190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
12200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         // Loop around to try calling sendfile again.
12210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *       }
12220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *     }
12230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
12240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *     // Pass result back to user's handler.
12250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *     handler_(ec, total_bytes_transferred_);
12260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   }
12270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * };
12280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
12290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * template <typename Handler>
12300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * void async_sendfile(tcp::socket& sock, int fd, Handler h)
12310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * {
12320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
12330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   sock.async_write_some(asio::null_buffers(), op);
12340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * } @endcode
12350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
12360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  void native_non_blocking(bool mode)
12370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
12380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::error_code ec;
12390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    this->get_service().native_non_blocking(
12400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        this->get_implementation(), mode, ec);
12410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::detail::throw_error(ec, "native_non_blocking");
12420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
12430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
12440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Sets the non-blocking mode of the native socket implementation.
12450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
12460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is used to modify the non-blocking mode of the underlying
12470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * native socket. It has no effect on the behaviour of the socket object's
12480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * synchronous operations.
12490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
12500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param mode If @c true, the underlying socket is put into non-blocking
12510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * mode and direct system calls may fail with asio::error::would_block
12520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * (or the equivalent system error).
12530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
12540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param ec Set to indicate what error occurred, if any. If the @c mode is
12550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @c false, but the current value of @c non_blocking() is @c true, this
12560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * function fails with asio::error::invalid_argument, as the
12570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * combination does not make sense.
12580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
12590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @par Example
12600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is intended to allow the encapsulation of arbitrary
12610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * non-blocking system calls as asynchronous operations, in a way that is
12620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * transparent to the user of the socket object. The following example
12630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * illustrates how Linux's @c sendfile system call might be encapsulated:
12640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @code template <typename Handler>
12650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * struct sendfile_op
12660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * {
12670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   tcp::socket& sock_;
12680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   int fd_;
12690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   Handler handler_;
12700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   off_t offset_;
12710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   std::size_t total_bytes_transferred_;
12720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
12730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   // Function call operator meeting WriteHandler requirements.
12740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   // Used as the handler for the async_write_some operation.
12750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   void operator()(asio::error_code ec, std::size_t)
12760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   {
12770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *     // Put the underlying socket into non-blocking mode.
12780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *     if (!ec)
12790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *       if (!sock_.native_non_blocking())
12800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         sock_.native_non_blocking(true, ec);
12810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
12820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *     if (!ec)
12830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *     {
12840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *       for (;;)
12850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *       {
12860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         // Try the system call.
12870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         errno = 0;
12880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);
12890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         ec = asio::error_code(n < 0 ? errno : 0,
12900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *             asio::error::get_system_category());
12910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         total_bytes_transferred_ += ec ? 0 : n;
12920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
12930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         // Retry operation immediately if interrupted by signal.
12940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         if (ec == asio::error::interrupted)
12950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *           continue;
12960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
12970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         // Check if we need to run the operation again.
12980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         if (ec == asio::error::would_block
12990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *             || ec == asio::error::try_again)
13000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         {
13010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *           // We have to wait for the socket to become ready again.
13020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *           sock_.async_write_some(asio::null_buffers(), *this);
13030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *           return;
13040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         }
13050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
13060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         if (ec || n == 0)
13070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         {
13080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *           // An error occurred, or we have reached the end of the file.
13090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *           // Either way we must exit the loop so we can call the handler.
13100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *           break;
13110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         }
13120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
13130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *         // Loop around to try calling sendfile again.
13140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *       }
13150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *     }
13160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
13170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *     // Pass result back to user's handler.
13180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *     handler_(ec, total_bytes_transferred_);
13190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   }
13200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * };
13210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
13220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * template <typename Handler>
13230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * void async_sendfile(tcp::socket& sock, int fd, Handler h)
13240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * {
13250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
13260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   sock.async_write_some(asio::null_buffers(), op);
13270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * } @endcode
13280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
13290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  asio::error_code native_non_blocking(
13300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      bool mode, asio::error_code& ec)
13310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
13320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return this->get_service().native_non_blocking(
13330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        this->get_implementation(), mode, ec);
13340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
13350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
13360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Get the local endpoint of the socket.
13370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
13380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is used to obtain the locally bound endpoint of the socket.
13390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
13400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @returns An object that represents the local endpoint of the socket.
13410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
13420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @throws asio::system_error Thrown on failure.
13430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
13440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @par Example
13450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @code
13460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::socket socket(io_service);
13470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * ...
13480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::endpoint endpoint = socket.local_endpoint();
13490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @endcode
13500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
13510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  endpoint_type local_endpoint() const
13520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
13530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::error_code ec;
13540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    endpoint_type ep = this->get_service().local_endpoint(
13550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        this->get_implementation(), ec);
13560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::detail::throw_error(ec, "local_endpoint");
13570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return ep;
13580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
13590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
13600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Get the local endpoint of the socket.
13610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
13620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is used to obtain the locally bound endpoint of the socket.
13630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
13640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param ec Set to indicate what error occurred, if any.
13650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
13660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @returns An object that represents the local endpoint of the socket.
13670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * Returns a default-constructed endpoint object if an error occurred.
13680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
13690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @par Example
13700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @code
13710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::socket socket(io_service);
13720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * ...
13730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::error_code ec;
13740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec);
13750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * if (ec)
13760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * {
13770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   // An error occurred.
13780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * }
13790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @endcode
13800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
13810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  endpoint_type local_endpoint(asio::error_code& ec) const
13820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
13830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return this->get_service().local_endpoint(this->get_implementation(), ec);
13840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
13850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
13860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Get the remote endpoint of the socket.
13870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
13880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is used to obtain the remote endpoint of the socket.
13890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
13900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @returns An object that represents the remote endpoint of the socket.
13910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
13920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @throws asio::system_error Thrown on failure.
13930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
13940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @par Example
13950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @code
13960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::socket socket(io_service);
13970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * ...
13980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::endpoint endpoint = socket.remote_endpoint();
13990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @endcode
14000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
14010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  endpoint_type remote_endpoint() const
14020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
14030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::error_code ec;
14040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    endpoint_type ep = this->get_service().remote_endpoint(
14050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        this->get_implementation(), ec);
14060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::detail::throw_error(ec, "remote_endpoint");
14070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return ep;
14080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
14090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
14100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Get the remote endpoint of the socket.
14110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
14120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is used to obtain the remote endpoint of the socket.
14130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
14140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param ec Set to indicate what error occurred, if any.
14150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
14160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @returns An object that represents the remote endpoint of the socket.
14170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * Returns a default-constructed endpoint object if an error occurred.
14180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
14190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @par Example
14200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @code
14210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::socket socket(io_service);
14220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * ...
14230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::error_code ec;
14240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec);
14250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * if (ec)
14260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * {
14270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   // An error occurred.
14280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * }
14290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @endcode
14300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
14310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  endpoint_type remote_endpoint(asio::error_code& ec) const
14320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
14330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return this->get_service().remote_endpoint(this->get_implementation(), ec);
14340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
14350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
14360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Disable sends or receives on the socket.
14370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
14380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is used to disable send operations, receive operations, or
14390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * both.
14400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
14410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param what Determines what types of operation will no longer be allowed.
14420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
14430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @throws asio::system_error Thrown on failure.
14440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
14450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @par Example
14460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * Shutting down the send side of the socket:
14470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @code
14480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::socket socket(io_service);
14490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * ...
14500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * socket.shutdown(asio::ip::tcp::socket::shutdown_send);
14510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @endcode
14520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
14530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  void shutdown(shutdown_type what)
14540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
14550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::error_code ec;
14560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    this->get_service().shutdown(this->get_implementation(), what, ec);
14570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::detail::throw_error(ec, "shutdown");
14580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
14590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
14600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Disable sends or receives on the socket.
14610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
14620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function is used to disable send operations, receive operations, or
14630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * both.
14640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
14650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param what Determines what types of operation will no longer be allowed.
14660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
14670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @param ec Set to indicate what error occurred, if any.
14680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
14690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @par Example
14700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * Shutting down the send side of the socket:
14710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @code
14720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::ip::tcp::socket socket(io_service);
14730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * ...
14740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * asio::error_code ec;
14750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * socket.shutdown(asio::ip::tcp::socket::shutdown_send, ec);
14760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * if (ec)
14770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * {
14780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *   // An error occurred.
14790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * }
14800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @endcode
14810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
14820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  asio::error_code shutdown(shutdown_type what,
14830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      asio::error_code& ec)
14840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
14850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return this->get_service().shutdown(this->get_implementation(), what, ec);
14860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
14870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
14880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieprotected:
14890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Protected destructor to prevent deletion through this type.
14900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  ~basic_socket()
14910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
14920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
14930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie};
14940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
14950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie} // namespace asio
14960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
14970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/pop_options.hpp"
14980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
14990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#endif // ASIO_BASIC_SOCKET_HPP
1500