diff options
| author | François Gaffie <francois.gaffie@intel.com> | 2016-02-17 07:59:02 +0100 |
|---|---|---|
| committer | Eric Laurent <elaurent@google.com> | 2016-03-04 17:47:35 -0800 |
| commit | 0ee85db398be8ea33d67cc42f99a1468cd6c8180 (patch) | |
| tree | 3b563dd1f477cff6b95a516cf9b121a461149f59 /asio-1.10.6/include | |
| parent | 221a25e58e92ebc450c7eaba5f3ba8153a2308ae (diff) | |
| download | platform_external_parameter-framework-0ee85db398be8ea33d67cc42f99a1468cd6c8180.tar.gz platform_external_parameter-framework-0ee85db398be8ea33d67cc42f99a1468cd6c8180.tar.bz2 platform_external_parameter-framework-0ee85db398be8ea33d67cc42f99a1468cd6c8180.zip | |
parameter-framework: add shrinked version of boost ASIO
Boost ASIO is a dependancy of Parameter framework v3.2.4.
As only used by PFW, as not provided by AOSP and as it is a quite huge
library, this patch adds the dependancy within PFW folder as a shrinked
version.
Bug: 22887211
Change-Id: Ie47b8cda7616214e06d2464fbb441abce367e7d4
Signed-off-by: François Gaffie <francois.gaffie@intel.com>
Diffstat (limited to 'asio-1.10.6/include')
153 files changed, 28102 insertions, 0 deletions
diff --git a/asio-1.10.6/include/asio/async_result.hpp b/asio-1.10.6/include/asio/async_result.hpp new file mode 100644 index 0000000..760ff14 --- /dev/null +++ b/asio-1.10.6/include/asio/async_result.hpp @@ -0,0 +1,81 @@ +// +// async_result.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_ASYNC_RESULT_HPP +#define ASIO_ASYNC_RESULT_HPP + + +#include "asio/detail/config.hpp" +#include "asio/handler_type.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +/// An interface for customising the behaviour of an initiating function. +/** + * This template may be specialised for user-defined handler types. + */ +template <typename Handler> +class async_result +{ +public: + /// The return type of the initiating function. + typedef void type; + + /// Construct an async result from a given handler. + /** + * When using a specalised async_result, the constructor has an opportunity + * to initialise some state associated with the handler, which is then + * returned from the initiating function. + */ + explicit async_result(Handler&) + { + } + + /// Obtain the value to be returned from the initiating function. + type get() + { + } +}; + +namespace detail { + +// Helper template to deduce the true type of a handler, capture a local copy +// of the handler, and then create an async_result for the handler. +template <typename Handler, typename Signature> +struct async_result_init +{ + explicit async_result_init(ASIO_MOVE_ARG(Handler) orig_handler) + : handler(ASIO_MOVE_CAST(Handler)(orig_handler)), + result(handler) + { + } + + typename handler_type<Handler, Signature>::type handler; + async_result<typename handler_type<Handler, Signature>::type> result; +}; + +template <typename Handler, typename Signature> +struct async_result_type_helper +{ + typedef typename async_result< + typename handler_type<Handler, Signature>::type + >::type type; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +# define ASIO_INITFN_RESULT_TYPE(h, sig) typename ::asio::async_result< typename ::asio::handler_type<h, sig>::type>::type + +#endif // ASIO_ASYNC_RESULT_HPP diff --git a/asio-1.10.6/include/asio/basic_io_object.hpp b/asio-1.10.6/include/asio/basic_io_object.hpp new file mode 100644 index 0000000..21a4882 --- /dev/null +++ b/asio-1.10.6/include/asio/basic_io_object.hpp @@ -0,0 +1,208 @@ +// +// basic_io_object.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_BASIC_IO_OBJECT_HPP +#define ASIO_BASIC_IO_OBJECT_HPP + + +#include "asio/detail/config.hpp" +#include "asio/io_service.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +namespace detail +{ + // Type trait used to determine whether a service supports move. + template <typename IoObjectService> + class service_has_move + { + private: + typedef IoObjectService service_type; + typedef typename service_type::implementation_type implementation_type; + + template <typename T, typename U> + static auto eval(T* t, U* u) -> decltype(t->move_construct(*u, *u), char()); + static char (&eval(...))[2]; + + public: + static const bool value = + sizeof(service_has_move::eval( + static_cast<service_type*>(0), + static_cast<implementation_type*>(0))) == 1; + }; +} + +/// Base class for all I/O objects. +/** + * @note All I/O objects are non-copyable. However, when using C++0x, certain + * I/O objects do support move construction and move assignment. + */ +template <typename IoObjectService, + bool Movable = detail::service_has_move<IoObjectService>::value> +class basic_io_object +{ +public: + /// The type of the service that will be used to provide I/O operations. + typedef IoObjectService service_type; + + /// The underlying implementation type of I/O object. + typedef typename service_type::implementation_type implementation_type; + + /// Get the io_service associated with the object. + /** + * This function may be used to obtain the io_service object that the I/O + * object uses to dispatch handlers for asynchronous operations. + * + * @return A reference to the io_service object that the I/O object will use + * to dispatch handlers. Ownership is not transferred to the caller. + */ + asio::io_service& get_io_service() + { + return service.get_io_service(); + } + +protected: + /// Construct a basic_io_object. + /** + * Performs: + * @code get_service().construct(get_implementation()); @endcode + */ + explicit basic_io_object(asio::io_service& io_service) + : service(asio::use_service<IoObjectService>(io_service)) + { + service.construct(implementation); + } + + + /// Protected destructor to prevent deletion through this type. + /** + * Performs: + * @code get_service().destroy(get_implementation()); @endcode + */ + ~basic_io_object() + { + service.destroy(implementation); + } + + /// Get the service associated with the I/O object. + service_type& get_service() + { + return service; + } + + /// Get the service associated with the I/O object. + const service_type& get_service() const + { + return service; + } + + /// (Deprecated: Use get_service().) The service associated with the I/O + /// object. + /** + * @note Available only for services that do not support movability. + */ + service_type& service; + + /// Get the underlying implementation of the I/O object. + implementation_type& get_implementation() + { + return implementation; + } + + /// Get the underlying implementation of the I/O object. + const implementation_type& get_implementation() const + { + return implementation; + } + + /// (Deprecated: Use get_implementation().) The underlying implementation of + /// the I/O object. + implementation_type implementation; + +private: + basic_io_object(const basic_io_object&); + basic_io_object& operator=(const basic_io_object&); +}; + +// Specialisation for movable objects. +template <typename IoObjectService> +class basic_io_object<IoObjectService, true> +{ +public: + typedef IoObjectService service_type; + typedef typename service_type::implementation_type implementation_type; + + asio::io_service& get_io_service() + { + return service_->get_io_service(); + } + +protected: + explicit basic_io_object(asio::io_service& io_service) + : service_(&asio::use_service<IoObjectService>(io_service)) + { + service_->construct(implementation); + } + + basic_io_object(basic_io_object&& other) + : service_(&other.get_service()) + { + service_->move_construct(implementation, other.implementation); + } + + ~basic_io_object() + { + service_->destroy(implementation); + } + + basic_io_object& operator=(basic_io_object&& other) + { + service_->move_assign(implementation, + *other.service_, other.implementation); + service_ = other.service_; + return *this; + } + + service_type& get_service() + { + return *service_; + } + + const service_type& get_service() const + { + return *service_; + } + + implementation_type& get_implementation() + { + return implementation; + } + + const implementation_type& get_implementation() const + { + return implementation; + } + + implementation_type implementation; + +private: + basic_io_object(const basic_io_object&); + void operator=(const basic_io_object&); + + IoObjectService* service_; +}; + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_BASIC_IO_OBJECT_HPP diff --git a/asio-1.10.6/include/asio/basic_socket.hpp b/asio-1.10.6/include/asio/basic_socket.hpp new file mode 100644 index 0000000..242929b --- /dev/null +++ b/asio-1.10.6/include/asio/basic_socket.hpp @@ -0,0 +1,1499 @@ +// +// basic_socket.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_BASIC_SOCKET_HPP +#define ASIO_BASIC_SOCKET_HPP + + +#include "asio/detail/config.hpp" +#include "asio/async_result.hpp" +#include "asio/basic_io_object.hpp" +#include "asio/detail/handler_type_requirements.hpp" +#include "asio/detail/throw_error.hpp" +#include "asio/detail/type_traits.hpp" +#include "asio/error.hpp" +#include "asio/socket_base.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +/// Provides socket functionality. +/** + * The basic_socket class template provides functionality that is common to both + * stream-oriented and datagram-oriented sockets. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template <typename Protocol, typename SocketService> +class basic_socket + : public basic_io_object<SocketService>, + public socket_base +{ +public: + /// (Deprecated: Use native_handle_type.) The native representation of a + /// socket. + typedef typename SocketService::native_handle_type native_type; + + /// The native representation of a socket. + typedef typename SocketService::native_handle_type native_handle_type; + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + /// A basic_socket is always the lowest layer. + typedef basic_socket<Protocol, SocketService> lowest_layer_type; + + /// Construct a basic_socket without opening it. + /** + * This constructor creates a socket without opening it. + * + * @param io_service The io_service object that the socket will use to + * dispatch handlers for any asynchronous operations performed on the socket. + */ + explicit basic_socket(asio::io_service& io_service) + : basic_io_object<SocketService>(io_service) + { + } + + /// Construct and open a basic_socket. + /** + * This constructor creates and opens a socket. + * + * @param io_service The io_service object that the socket will use to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws asio::system_error Thrown on failure. + */ + basic_socket(asio::io_service& io_service, + const protocol_type& protocol) + : basic_io_object<SocketService>(io_service) + { + asio::error_code ec; + this->get_service().open(this->get_implementation(), protocol, ec); + asio::detail::throw_error(ec, "open"); + } + + /// Construct a basic_socket, opening it and binding it to the given local + /// endpoint. + /** + * This constructor creates a socket and automatically opens it bound to the + * specified endpoint on the local machine. The protocol used is the protocol + * associated with the given endpoint. + * + * @param io_service The io_service object that the socket will use to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param endpoint An endpoint on the local machine to which the socket will + * be bound. + * + * @throws asio::system_error Thrown on failure. + */ + basic_socket(asio::io_service& io_service, + const endpoint_type& endpoint) + : basic_io_object<SocketService>(io_service) + { + asio::error_code ec; + const protocol_type protocol = endpoint.protocol(); + this->get_service().open(this->get_implementation(), protocol, ec); + asio::detail::throw_error(ec, "open"); + this->get_service().bind(this->get_implementation(), endpoint, ec); + asio::detail::throw_error(ec, "bind"); + } + + /// Construct a basic_socket on an existing native socket. + /** + * This constructor creates a socket object to hold an existing native socket. + * + * @param io_service The io_service object that the socket will use to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_socket A native socket. + * + * @throws asio::system_error Thrown on failure. + */ + basic_socket(asio::io_service& io_service, + const protocol_type& protocol, const native_handle_type& native_socket) + : basic_io_object<SocketService>(io_service) + { + asio::error_code ec; + this->get_service().assign(this->get_implementation(), + protocol, native_socket, ec); + asio::detail::throw_error(ec, "assign"); + } + + /// Move-construct a basic_socket from another. + /** + * This constructor moves a socket from one object to another. + * + * @param other The other basic_socket object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket(io_service&) constructor. + */ + basic_socket(basic_socket&& other) + : basic_io_object<SocketService>( + ASIO_MOVE_CAST(basic_socket)(other)) + { + } + + /// Move-assign a basic_socket from another. + /** + * This assignment operator moves a socket from one object to another. + * + * @param other The other basic_socket object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket(io_service&) constructor. + */ + basic_socket& operator=(basic_socket&& other) + { + basic_io_object<SocketService>::operator=( + ASIO_MOVE_CAST(basic_socket)(other)); + return *this; + } + + // All sockets have access to each other's implementations. + template <typename Protocol1, typename SocketService1> + friend class basic_socket; + + /// Move-construct a basic_socket from a socket of another protocol type. + /** + * This constructor moves a socket from one object to another. + * + * @param other The other basic_socket object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket(io_service&) constructor. + */ + template <typename Protocol1, typename SocketService1> + basic_socket(basic_socket<Protocol1, SocketService1>&& other, + typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0) + : basic_io_object<SocketService>(other.get_io_service()) + { + this->get_service().template converting_move_construct<Protocol1>( + this->get_implementation(), other.get_implementation()); + } + + /// Move-assign a basic_socket from a socket of another protocol type. + /** + * This assignment operator moves a socket from one object to another. + * + * @param other The other basic_socket object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket(io_service&) constructor. + */ + template <typename Protocol1, typename SocketService1> + typename enable_if<is_convertible<Protocol1, Protocol>::value, + basic_socket>::type& operator=( + basic_socket<Protocol1, SocketService1>&& other) + { + basic_socket tmp(ASIO_MOVE_CAST2(basic_socket< + Protocol1, SocketService1>)(other)); + basic_io_object<SocketService>::operator=( + ASIO_MOVE_CAST(basic_socket)(tmp)); + return *this; + } + + /// Get a reference to the lowest layer. + /** + * This function returns a reference to the lowest layer in a stack of + * layers. Since a basic_socket cannot contain any further layers, it simply + * returns a reference to itself. + * + * @return A reference to the lowest layer in the stack of layers. Ownership + * is not transferred to the caller. + */ + lowest_layer_type& lowest_layer() + { + return *this; + } + + /// Get a const reference to the lowest layer. + /** + * This function returns a const reference to the lowest layer in a stack of + * layers. Since a basic_socket cannot contain any further layers, it simply + * returns a reference to itself. + * + * @return A const reference to the lowest layer in the stack of layers. + * Ownership is not transferred to the caller. + */ + const lowest_layer_type& lowest_layer() const + { + return *this; + } + + /// Open the socket using the specified protocol. + /** + * This function opens the socket so that it will use the specified protocol. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws asio::system_error Thrown on failure. + * + * @par Example + * @code + * asio::ip::tcp::socket socket(io_service); + * socket.open(asio::ip::tcp::v4()); + * @endcode + */ + void open(const protocol_type& protocol = protocol_type()) + { + asio::error_code ec; + this->get_service().open(this->get_implementation(), protocol, ec); + asio::detail::throw_error(ec, "open"); + } + + /// Open the socket using the specified protocol. + /** + * This function opens the socket so that it will use the specified protocol. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * asio::ip::tcp::socket socket(io_service); + * asio::error_code ec; + * socket.open(asio::ip::tcp::v4(), ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + asio::error_code open(const protocol_type& protocol, + asio::error_code& ec) + { + return this->get_service().open(this->get_implementation(), protocol, ec); + } + + /// Assign an existing native socket to the socket. + /* + * This function opens the socket to hold an existing native socket. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param native_socket A native socket. + * + * @throws asio::system_error Thrown on failure. + */ + void assign(const protocol_type& protocol, + const native_handle_type& native_socket) + { + asio::error_code ec; + this->get_service().assign(this->get_implementation(), + protocol, native_socket, ec); + asio::detail::throw_error(ec, "assign"); + } + + /// Assign an existing native socket to the socket. + /* + * This function opens the socket to hold an existing native socket. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param native_socket A native socket. + * + * @param ec Set to indicate what error occurred, if any. + */ + asio::error_code assign(const protocol_type& protocol, + const native_handle_type& native_socket, asio::error_code& ec) + { + return this->get_service().assign(this->get_implementation(), + protocol, native_socket, ec); + } + + /// Determine whether the socket is open. + bool is_open() const + { + return this->get_service().is_open(this->get_implementation()); + } + + /// Close the socket. + /** + * This function is used to close the socket. Any asynchronous send, receive + * or connect operations will be cancelled immediately, and will complete + * with the asio::error::operation_aborted error. + * + * @throws asio::system_error Thrown on failure. Note that, even if + * the function indicates an error, the underlying descriptor is closed. + * + * @note For portable behaviour with respect to graceful closure of a + * connected socket, call shutdown() before closing the socket. + */ + void close() + { + asio::error_code ec; + this->get_service().close(this->get_implementation(), ec); + asio::detail::throw_error(ec, "close"); + } + + /// Close the socket. + /** + * This function is used to close the socket. Any asynchronous send, receive + * or connect operations will be cancelled immediately, and will complete + * with the asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. Note that, even if + * the function indicates an error, the underlying descriptor is closed. + * + * @par Example + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::error_code ec; + * socket.close(ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + * + * @note For portable behaviour with respect to graceful closure of a + * connected socket, call shutdown() before closing the socket. + */ + asio::error_code close(asio::error_code& ec) + { + return this->get_service().close(this->get_implementation(), ec); + } + + /// (Deprecated: Use native_handle().) Get the native socket representation. + /** + * This function may be used to obtain the underlying representation of the + * socket. This is intended to allow access to native socket functionality + * that is not otherwise provided. + */ + native_type native() + { + return this->get_service().native_handle(this->get_implementation()); + } + + /// Get the native socket representation. + /** + * This function may be used to obtain the underlying representation of the + * socket. This is intended to allow access to native socket functionality + * that is not otherwise provided. + */ + native_handle_type native_handle() + { + return this->get_service().native_handle(this->get_implementation()); + } + + /// Cancel all asynchronous operations associated with the socket. + /** + * This function causes all outstanding asynchronous connect, send and receive + * operations to finish immediately, and the handlers for cancelled operations + * will be passed the asio::error::operation_aborted error. + * + * @throws asio::system_error Thrown on failure. + * + * @note Calls to cancel() will always fail with + * asio::error::operation_not_supported when run on Windows XP, Windows + * Server 2003, and earlier versions of Windows, unless + * ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has + * two issues that should be considered before enabling its use: + * + * @li It will only cancel asynchronous operations that were initiated in the + * current thread. + * + * @li It can appear to complete without error, but the request to cancel the + * unfinished operations may be silently ignored by the operating system. + * Whether it works or not seems to depend on the drivers that are installed. + * + * For portable cancellation, consider using one of the following + * alternatives: + * + * @li Disable asio's I/O completion port backend by defining + * ASIO_DISABLE_IOCP. + * + * @li Use the close() function to simultaneously cancel the outstanding + * operations and close the socket. + * + * When running on Windows Vista, Windows Server 2008, and later, the + * CancelIoEx function is always used. This function does not have the + * problems described above. + */ + void cancel() + { + asio::error_code ec; + this->get_service().cancel(this->get_implementation(), ec); + asio::detail::throw_error(ec, "cancel"); + } + + /// Cancel all asynchronous operations associated with the socket. + /** + * This function causes all outstanding asynchronous connect, send and receive + * operations to finish immediately, and the handlers for cancelled operations + * will be passed the asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + * + * @note Calls to cancel() will always fail with + * asio::error::operation_not_supported when run on Windows XP, Windows + * Server 2003, and earlier versions of Windows, unless + * ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has + * two issues that should be considered before enabling its use: + * + * @li It will only cancel asynchronous operations that were initiated in the + * current thread. + * + * @li It can appear to complete without error, but the request to cancel the + * unfinished operations may be silently ignored by the operating system. + * Whether it works or not seems to depend on the drivers that are installed. + * + * For portable cancellation, consider using one of the following + * alternatives: + * + * @li Disable asio's I/O completion port backend by defining + * ASIO_DISABLE_IOCP. + * + * @li Use the close() function to simultaneously cancel the outstanding + * operations and close the socket. + * + * When running on Windows Vista, Windows Server 2008, and later, the + * CancelIoEx function is always used. This function does not have the + * problems described above. + */ + asio::error_code cancel(asio::error_code& ec) + { + return this->get_service().cancel(this->get_implementation(), ec); + } + + /// Determine whether the socket is at the out-of-band data mark. + /** + * This function is used to check whether the socket input is currently + * positioned at the out-of-band data mark. + * + * @return A bool indicating whether the socket is at the out-of-band data + * mark. + * + * @throws asio::system_error Thrown on failure. + */ + bool at_mark() const + { + asio::error_code ec; + bool b = this->get_service().at_mark(this->get_implementation(), ec); + asio::detail::throw_error(ec, "at_mark"); + return b; + } + + /// Determine whether the socket is at the out-of-band data mark. + /** + * This function is used to check whether the socket input is currently + * positioned at the out-of-band data mark. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return A bool indicating whether the socket is at the out-of-band data + * mark. + */ + bool at_mark(asio::error_code& ec) const + { + return this->get_service().at_mark(this->get_implementation(), ec); + } + + /// Determine the number of bytes available for reading. + /** + * This function is used to determine the number of bytes that may be read + * without blocking. + * + * @return The number of bytes that may be read without blocking, or 0 if an + * error occurs. + * + * @throws asio::system_error Thrown on failure. + */ + std::size_t available() const + { + asio::error_code ec; + std::size_t s = this->get_service().available( + this->get_implementation(), ec); + asio::detail::throw_error(ec, "available"); + return s; + } + + /// Determine the number of bytes available for reading. + /** + * This function is used to determine the number of bytes that may be read + * without blocking. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return The number of bytes that may be read without blocking, or 0 if an + * error occurs. + */ + std::size_t available(asio::error_code& ec) const + { + return this->get_service().available(this->get_implementation(), ec); + } + + /// Bind the socket to the given local endpoint. + /** + * This function binds the socket to the specified endpoint on the local + * machine. + * + * @param endpoint An endpoint on the local machine to which the socket will + * be bound. + * + * @throws asio::system_error Thrown on failure. + * + * @par Example + * @code + * asio::ip::tcp::socket socket(io_service); + * socket.open(asio::ip::tcp::v4()); + * socket.bind(asio::ip::tcp::endpoint( + * asio::ip::tcp::v4(), 12345)); + * @endcode + */ + void bind(const endpoint_type& endpoint) + { + asio::error_code ec; + this->get_service().bind(this->get_implementation(), endpoint, ec); + asio::detail::throw_error(ec, "bind"); + } + + /// Bind the socket to the given local endpoint. + /** + * This function binds the socket to the specified endpoint on the local + * machine. + * + * @param endpoint An endpoint on the local machine to which the socket will + * be bound. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * asio::ip::tcp::socket socket(io_service); + * socket.open(asio::ip::tcp::v4()); + * asio::error_code ec; + * socket.bind(asio::ip::tcp::endpoint( + * asio::ip::tcp::v4(), 12345), ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + asio::error_code bind(const endpoint_type& endpoint, + asio::error_code& ec) + { + return this->get_service().bind(this->get_implementation(), endpoint, ec); + } + + /// Connect the socket to the specified endpoint. + /** + * This function is used to connect a socket to the specified remote endpoint. + * The function call will block until the connection is successfully made or + * an error occurs. + * + * The socket is automatically opened if it is not already open. If the + * connect fails, and the socket was automatically opened, the socket is + * not returned to the closed state. + * + * @param peer_endpoint The remote endpoint to which the socket will be + * connected. + * + * @throws asio::system_error Thrown on failure. + * + * @par Example + * @code + * asio::ip::tcp::socket socket(io_service); + * asio::ip::tcp::endpoint endpoint( + * asio::ip::address::from_string("1.2.3.4"), 12345); + * socket.connect(endpoint); + * @endcode + */ + void connect(const endpoint_type& peer_endpoint) + { + asio::error_code ec; + if (!is_open()) + { + this->get_service().open(this->get_implementation(), + peer_endpoint.protocol(), ec); + asio::detail::throw_error(ec, "connect"); + } + this->get_service().connect(this->get_implementation(), peer_endpoint, ec); + asio::detail::throw_error(ec, "connect"); + } + + /// Connect the socket to the specified endpoint. + /** + * This function is used to connect a socket to the specified remote endpoint. + * The function call will block until the connection is successfully made or + * an error occurs. + * + * The socket is automatically opened if it is not already open. If the + * connect fails, and the socket was automatically opened, the socket is + * not returned to the closed state. + * + * @param peer_endpoint The remote endpoint to which the socket will be + * connected. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * asio::ip::tcp::socket socket(io_service); + * asio::ip::tcp::endpoint endpoint( + * asio::ip::address::from_string("1.2.3.4"), 12345); + * asio::error_code ec; + * socket.connect(endpoint, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + asio::error_code connect(const endpoint_type& peer_endpoint, + asio::error_code& ec) + { + if (!is_open()) + { + if (this->get_service().open(this->get_implementation(), + peer_endpoint.protocol(), ec)) + { + return ec; + } + } + + return this->get_service().connect( + this->get_implementation(), peer_endpoint, ec); + } + + /// Start an asynchronous connect. + /** + * This function is used to asynchronously connect a socket to the specified + * remote endpoint. The function call always returns immediately. + * + * The socket is automatically opened if it is not already open. If the + * connect fails, and the socket was automatically opened, the socket is + * not returned to the closed state. + * + * @param peer_endpoint The remote endpoint to which the socket will be + * connected. Copies will be made of the endpoint object as required. + * + * @param handler The handler to be called when the connection operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const asio::error_code& error // Result of operation + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @par Example + * @code + * void connect_handler(const asio::error_code& error) + * { + * if (!error) + * { + * // Connect succeeded. + * } + * } + * + * ... + * + * asio::ip::tcp::socket socket(io_service); + * asio::ip::tcp::endpoint endpoint( + * asio::ip::address::from_string("1.2.3.4"), 12345); + * socket.async_connect(endpoint, connect_handler); + * @endcode + */ + template <typename ConnectHandler> + ASIO_INITFN_RESULT_TYPE(ConnectHandler, + void (asio::error_code)) + async_connect(const endpoint_type& peer_endpoint, + ASIO_MOVE_ARG(ConnectHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ConnectHandler. + ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check; + + if (!is_open()) + { + asio::error_code ec; + const protocol_type protocol = peer_endpoint.protocol(); + if (this->get_service().open(this->get_implementation(), protocol, ec)) + { + detail::async_result_init< + ConnectHandler, void (asio::error_code)> init( + ASIO_MOVE_CAST(ConnectHandler)(handler)); + + this->get_io_service().post( + asio::detail::bind_handler( + ASIO_MOVE_CAST(ASIO_HANDLER_TYPE( + ConnectHandler, void (asio::error_code)))( + init.handler), ec)); + + return init.result.get(); + } + } + + return this->get_service().async_connect(this->get_implementation(), + peer_endpoint, ASIO_MOVE_CAST(ConnectHandler)(handler)); + } + + /// Set an option on the socket. + /** + * This function is used to set an option on the socket. + * + * @param option The new option value to be set on the socket. + * + * @throws asio::system_error Thrown on failure. + * + * @sa SettableSocketOption @n + * asio::socket_base::broadcast @n + * asio::socket_base::do_not_route @n + * asio::socket_base::keep_alive @n + * asio::socket_base::linger @n + * asio::socket_base::receive_buffer_size @n + * asio::socket_base::receive_low_watermark @n + * asio::socket_base::reuse_address @n + * asio::socket_base::send_buffer_size @n + * asio::socket_base::send_low_watermark @n + * asio::ip::multicast::join_group @n + * asio::ip::multicast::leave_group @n + * asio::ip::multicast::enable_loopback @n + * asio::ip::multicast::outbound_interface @n + * asio::ip::multicast::hops @n + * asio::ip::tcp::no_delay + * + * @par Example + * Setting the IPPROTO_TCP/TCP_NODELAY option: + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::ip::tcp::no_delay option(true); + * socket.set_option(option); + * @endcode + */ + template <typename SettableSocketOption> + void set_option(const SettableSocketOption& option) + { + asio::error_code ec; + this->get_service().set_option(this->get_implementation(), option, ec); + asio::detail::throw_error(ec, "set_option"); + } + + /// Set an option on the socket. + /** + * This function is used to set an option on the socket. + * + * @param option The new option value to be set on the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa SettableSocketOption @n + * asio::socket_base::broadcast @n + * asio::socket_base::do_not_route @n + * asio::socket_base::keep_alive @n + * asio::socket_base::linger @n + * asio::socket_base::receive_buffer_size @n + * asio::socket_base::receive_low_watermark @n + * asio::socket_base::reuse_address @n + * asio::socket_base::send_buffer_size @n + * asio::socket_base::send_low_watermark @n + * asio::ip::multicast::join_group @n + * asio::ip::multicast::leave_group @n + * asio::ip::multicast::enable_loopback @n + * asio::ip::multicast::outbound_interface @n + * asio::ip::multicast::hops @n + * asio::ip::tcp::no_delay + * + * @par Example + * Setting the IPPROTO_TCP/TCP_NODELAY option: + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::ip::tcp::no_delay option(true); + * asio::error_code ec; + * socket.set_option(option, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template <typename SettableSocketOption> + asio::error_code set_option(const SettableSocketOption& option, + asio::error_code& ec) + { + return this->get_service().set_option( + this->get_implementation(), option, ec); + } + + /// Get an option from the socket. + /** + * This function is used to get the current value of an option on the socket. + * + * @param option The option value to be obtained from the socket. + * + * @throws asio::system_error Thrown on failure. + * + * @sa GettableSocketOption @n + * asio::socket_base::broadcast @n + * asio::socket_base::do_not_route @n + * asio::socket_base::keep_alive @n + * asio::socket_base::linger @n + * asio::socket_base::receive_buffer_size @n + * asio::socket_base::receive_low_watermark @n + * asio::socket_base::reuse_address @n + * asio::socket_base::send_buffer_size @n + * asio::socket_base::send_low_watermark @n + * asio::ip::multicast::join_group @n + * asio::ip::multicast::leave_group @n + * asio::ip::multicast::enable_loopback @n + * asio::ip::multicast::outbound_interface @n + * asio::ip::multicast::hops @n + * asio::ip::tcp::no_delay + * + * @par Example + * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::ip::tcp::socket::keep_alive option; + * socket.get_option(option); + * bool is_set = option.value(); + * @endcode + */ + template <typename GettableSocketOption> + void get_option(GettableSocketOption& option) const + { + asio::error_code ec; + this->get_service().get_option(this->get_implementation(), option, ec); + asio::detail::throw_error(ec, "get_option"); + } + + /// Get an option from the socket. + /** + * This function is used to get the current value of an option on the socket. + * + * @param option The option value to be obtained from the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa GettableSocketOption @n + * asio::socket_base::broadcast @n + * asio::socket_base::do_not_route @n + * asio::socket_base::keep_alive @n + * asio::socket_base::linger @n + * asio::socket_base::receive_buffer_size @n + * asio::socket_base::receive_low_watermark @n + * asio::socket_base::reuse_address @n + * asio::socket_base::send_buffer_size @n + * asio::socket_base::send_low_watermark @n + * asio::ip::multicast::join_group @n + * asio::ip::multicast::leave_group @n + * asio::ip::multicast::enable_loopback @n + * asio::ip::multicast::outbound_interface @n + * asio::ip::multicast::hops @n + * asio::ip::tcp::no_delay + * + * @par Example + * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::ip::tcp::socket::keep_alive option; + * asio::error_code ec; + * socket.get_option(option, ec); + * if (ec) + * { + * // An error occurred. + * } + * bool is_set = option.value(); + * @endcode + */ + template <typename GettableSocketOption> + asio::error_code get_option(GettableSocketOption& option, + asio::error_code& ec) const + { + return this->get_service().get_option( + this->get_implementation(), option, ec); + } + + /// Perform an IO control command on the socket. + /** + * This function is used to execute an IO control command on the socket. + * + * @param command The IO control command to be performed on the socket. + * + * @throws asio::system_error Thrown on failure. + * + * @sa IoControlCommand @n + * asio::socket_base::bytes_readable @n + * asio::socket_base::non_blocking_io + * + * @par Example + * Getting the number of bytes ready to read: + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::ip::tcp::socket::bytes_readable command; + * socket.io_control(command); + * std::size_t bytes_readable = command.get(); + * @endcode + */ + template <typename IoControlCommand> + void io_control(IoControlCommand& command) + { + asio::error_code ec; + this->get_service().io_control(this->get_implementation(), command, ec); + asio::detail::throw_error(ec, "io_control"); + } + + /// Perform an IO control command on the socket. + /** + * This function is used to execute an IO control command on the socket. + * + * @param command The IO control command to be performed on the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa IoControlCommand @n + * asio::socket_base::bytes_readable @n + * asio::socket_base::non_blocking_io + * + * @par Example + * Getting the number of bytes ready to read: + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::ip::tcp::socket::bytes_readable command; + * asio::error_code ec; + * socket.io_control(command, ec); + * if (ec) + * { + * // An error occurred. + * } + * std::size_t bytes_readable = command.get(); + * @endcode + */ + template <typename IoControlCommand> + asio::error_code io_control(IoControlCommand& command, + asio::error_code& ec) + { + return this->get_service().io_control( + this->get_implementation(), command, ec); + } + + /// Gets the non-blocking mode of the socket. + /** + * @returns @c true if the socket's synchronous operations will fail with + * asio::error::would_block if they are unable to perform the requested + * operation immediately. If @c false, synchronous operations will block + * until complete. + * + * @note The non-blocking mode has no effect on the behaviour of asynchronous + * operations. Asynchronous operations will never fail with the error + * asio::error::would_block. + */ + bool non_blocking() const + { + return this->get_service().non_blocking(this->get_implementation()); + } + + /// Sets the non-blocking mode of the socket. + /** + * @param mode If @c true, the socket's synchronous operations will fail with + * asio::error::would_block if they are unable to perform the requested + * operation immediately. If @c false, synchronous operations will block + * until complete. + * + * @throws asio::system_error Thrown on failure. + * + * @note The non-blocking mode has no effect on the behaviour of asynchronous + * operations. Asynchronous operations will never fail with the error + * asio::error::would_block. + */ + void non_blocking(bool mode) + { + asio::error_code ec; + this->get_service().non_blocking(this->get_implementation(), mode, ec); + asio::detail::throw_error(ec, "non_blocking"); + } + + /// Sets the non-blocking mode of the socket. + /** + * @param mode If @c true, the socket's synchronous operations will fail with + * asio::error::would_block if they are unable to perform the requested + * operation immediately. If @c false, synchronous operations will block + * until complete. + * + * @param ec Set to indicate what error occurred, if any. + * + * @note The non-blocking mode has no effect on the behaviour of asynchronous + * operations. Asynchronous operations will never fail with the error + * asio::error::would_block. + */ + asio::error_code non_blocking( + bool mode, asio::error_code& ec) + { + return this->get_service().non_blocking( + this->get_implementation(), mode, ec); + } + + /// Gets the non-blocking mode of the native socket implementation. + /** + * This function is used to retrieve the non-blocking mode of the underlying + * native socket. This mode has no effect on the behaviour of the socket + * object's synchronous operations. + * + * @returns @c true if the underlying socket is in non-blocking mode and + * direct system calls may fail with asio::error::would_block (or the + * equivalent system error). + * + * @note The current non-blocking mode is cached by the socket object. + * Consequently, the return value may be incorrect if the non-blocking mode + * was set directly on the native socket. + * + * @par Example + * This function is intended to allow the encapsulation of arbitrary + * non-blocking system calls as asynchronous operations, in a way that is + * transparent to the user of the socket object. The following example + * illustrates how Linux's @c sendfile system call might be encapsulated: + * @code template <typename Handler> + * struct sendfile_op + * { + * tcp::socket& sock_; + * int fd_; + * Handler handler_; + * off_t offset_; + * std::size_t total_bytes_transferred_; + * + * // Function call operator meeting WriteHandler requirements. + * // Used as the handler for the async_write_some operation. + * void operator()(asio::error_code ec, std::size_t) + * { + * // Put the underlying socket into non-blocking mode. + * if (!ec) + * if (!sock_.native_non_blocking()) + * sock_.native_non_blocking(true, ec); + * + * if (!ec) + * { + * for (;;) + * { + * // Try the system call. + * errno = 0; + * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + * ec = asio::error_code(n < 0 ? errno : 0, + * asio::error::get_system_category()); + * total_bytes_transferred_ += ec ? 0 : n; + * + * // Retry operation immediately if interrupted by signal. + * if (ec == asio::error::interrupted) + * continue; + * + * // Check if we need to run the operation again. + * if (ec == asio::error::would_block + * || ec == asio::error::try_again) + * { + * // We have to wait for the socket to become ready again. + * sock_.async_write_some(asio::null_buffers(), *this); + * return; + * } + * + * if (ec || n == 0) + * { + * // An error occurred, or we have reached the end of the file. + * // Either way we must exit the loop so we can call the handler. + * break; + * } + * + * // Loop around to try calling sendfile again. + * } + * } + * + * // Pass result back to user's handler. + * handler_(ec, total_bytes_transferred_); + * } + * }; + * + * template <typename Handler> + * void async_sendfile(tcp::socket& sock, int fd, Handler h) + * { + * sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; + * sock.async_write_some(asio::null_buffers(), op); + * } @endcode + */ + bool native_non_blocking() const + { + return this->get_service().native_non_blocking(this->get_implementation()); + } + + /// Sets the non-blocking mode of the native socket implementation. + /** + * This function is used to modify the non-blocking mode of the underlying + * native socket. It has no effect on the behaviour of the socket object's + * synchronous operations. + * + * @param mode If @c true, the underlying socket is put into non-blocking + * mode and direct system calls may fail with asio::error::would_block + * (or the equivalent system error). + * + * @throws asio::system_error Thrown on failure. If the @c mode is + * @c false, but the current value of @c non_blocking() is @c true, this + * function fails with asio::error::invalid_argument, as the + * combination does not make sense. + * + * @par Example + * This function is intended to allow the encapsulation of arbitrary + * non-blocking system calls as asynchronous operations, in a way that is + * transparent to the user of the socket object. The following example + * illustrates how Linux's @c sendfile system call might be encapsulated: + * @code template <typename Handler> + * struct sendfile_op + * { + * tcp::socket& sock_; + * int fd_; + * Handler handler_; + * off_t offset_; + * std::size_t total_bytes_transferred_; + * + * // Function call operator meeting WriteHandler requirements. + * // Used as the handler for the async_write_some operation. + * void operator()(asio::error_code ec, std::size_t) + * { + * // Put the underlying socket into non-blocking mode. + * if (!ec) + * if (!sock_.native_non_blocking()) + * sock_.native_non_blocking(true, ec); + * + * if (!ec) + * { + * for (;;) + * { + * // Try the system call. + * errno = 0; + * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + * ec = asio::error_code(n < 0 ? errno : 0, + * asio::error::get_system_category()); + * total_bytes_transferred_ += ec ? 0 : n; + * + * // Retry operation immediately if interrupted by signal. + * if (ec == asio::error::interrupted) + * continue; + * + * // Check if we need to run the operation again. + * if (ec == asio::error::would_block + * || ec == asio::error::try_again) + * { + * // We have to wait for the socket to become ready again. + * sock_.async_write_some(asio::null_buffers(), *this); + * return; + * } + * + * if (ec || n == 0) + * { + * // An error occurred, or we have reached the end of the file. + * // Either way we must exit the loop so we can call the handler. + * break; + * } + * + * // Loop around to try calling sendfile again. + * } + * } + * + * // Pass result back to user's handler. + * handler_(ec, total_bytes_transferred_); + * } + * }; + * + * template <typename Handler> + * void async_sendfile(tcp::socket& sock, int fd, Handler h) + * { + * sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; + * sock.async_write_some(asio::null_buffers(), op); + * } @endcode + */ + void native_non_blocking(bool mode) + { + asio::error_code ec; + this->get_service().native_non_blocking( + this->get_implementation(), mode, ec); + asio::detail::throw_error(ec, "native_non_blocking"); + } + + /// Sets the non-blocking mode of the native socket implementation. + /** + * This function is used to modify the non-blocking mode of the underlying + * native socket. It has no effect on the behaviour of the socket object's + * synchronous operations. + * + * @param mode If @c true, the underlying socket is put into non-blocking + * mode and direct system calls may fail with asio::error::would_block + * (or the equivalent system error). + * + * @param ec Set to indicate what error occurred, if any. If the @c mode is + * @c false, but the current value of @c non_blocking() is @c true, this + * function fails with asio::error::invalid_argument, as the + * combination does not make sense. + * + * @par Example + * This function is intended to allow the encapsulation of arbitrary + * non-blocking system calls as asynchronous operations, in a way that is + * transparent to the user of the socket object. The following example + * illustrates how Linux's @c sendfile system call might be encapsulated: + * @code template <typename Handler> + * struct sendfile_op + * { + * tcp::socket& sock_; + * int fd_; + * Handler handler_; + * off_t offset_; + * std::size_t total_bytes_transferred_; + * + * // Function call operator meeting WriteHandler requirements. + * // Used as the handler for the async_write_some operation. + * void operator()(asio::error_code ec, std::size_t) + * { + * // Put the underlying socket into non-blocking mode. + * if (!ec) + * if (!sock_.native_non_blocking()) + * sock_.native_non_blocking(true, ec); + * + * if (!ec) + * { + * for (;;) + * { + * // Try the system call. + * errno = 0; + * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + * ec = asio::error_code(n < 0 ? errno : 0, + * asio::error::get_system_category()); + * total_bytes_transferred_ += ec ? 0 : n; + * + * // Retry operation immediately if interrupted by signal. + * if (ec == asio::error::interrupted) + * continue; + * + * // Check if we need to run the operation again. + * if (ec == asio::error::would_block + * || ec == asio::error::try_again) + * { + * // We have to wait for the socket to become ready again. + * sock_.async_write_some(asio::null_buffers(), *this); + * return; + * } + * + * if (ec || n == 0) + * { + * // An error occurred, or we have reached the end of the file. + * // Either way we must exit the loop so we can call the handler. + * break; + * } + * + * // Loop around to try calling sendfile again. + * } + * } + * + * // Pass result back to user's handler. + * handler_(ec, total_bytes_transferred_); + * } + * }; + * + * template <typename Handler> + * void async_sendfile(tcp::socket& sock, int fd, Handler h) + * { + * sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; + * sock.async_write_some(asio::null_buffers(), op); + * } @endcode + */ + asio::error_code native_non_blocking( + bool mode, asio::error_code& ec) + { + return this->get_service().native_non_blocking( + this->get_implementation(), mode, ec); + } + + /// Get the local endpoint of the socket. + /** + * This function is used to obtain the locally bound endpoint of the socket. + * + * @returns An object that represents the local endpoint of the socket. + * + * @throws asio::system_error Thrown on failure. + * + * @par Example + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::ip::tcp::endpoint endpoint = socket.local_endpoint(); + * @endcode + */ + endpoint_type local_endpoint() const + { + asio::error_code ec; + endpoint_type ep = this->get_service().local_endpoint( + this->get_implementation(), ec); + asio::detail::throw_error(ec, "local_endpoint"); + return ep; + } + + /// Get the local endpoint of the socket. + /** + * This function is used to obtain the locally bound endpoint of the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns An object that represents the local endpoint of the socket. + * Returns a default-constructed endpoint object if an error occurred. + * + * @par Example + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::error_code ec; + * asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + endpoint_type local_endpoint(asio::error_code& ec) const + { + return this->get_service().local_endpoint(this->get_implementation(), ec); + } + + /// Get the remote endpoint of the socket. + /** + * This function is used to obtain the remote endpoint of the socket. + * + * @returns An object that represents the remote endpoint of the socket. + * + * @throws asio::system_error Thrown on failure. + * + * @par Example + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(); + * @endcode + */ + endpoint_type remote_endpoint() const + { + asio::error_code ec; + endpoint_type ep = this->get_service().remote_endpoint( + this->get_implementation(), ec); + asio::detail::throw_error(ec, "remote_endpoint"); + return ep; + } + + /// Get the remote endpoint of the socket. + /** + * This function is used to obtain the remote endpoint of the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns An object that represents the remote endpoint of the socket. + * Returns a default-constructed endpoint object if an error occurred. + * + * @par Example + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::error_code ec; + * asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + endpoint_type remote_endpoint(asio::error_code& ec) const + { + return this->get_service().remote_endpoint(this->get_implementation(), ec); + } + + /// Disable sends or receives on the socket. + /** + * This function is used to disable send operations, receive operations, or + * both. + * + * @param what Determines what types of operation will no longer be allowed. + * + * @throws asio::system_error Thrown on failure. + * + * @par Example + * Shutting down the send side of the socket: + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * socket.shutdown(asio::ip::tcp::socket::shutdown_send); + * @endcode + */ + void shutdown(shutdown_type what) + { + asio::error_code ec; + this->get_service().shutdown(this->get_implementation(), what, ec); + asio::detail::throw_error(ec, "shutdown"); + } + + /// Disable sends or receives on the socket. + /** + * This function is used to disable send operations, receive operations, or + * both. + * + * @param what Determines what types of operation will no longer be allowed. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * Shutting down the send side of the socket: + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::error_code ec; + * socket.shutdown(asio::ip::tcp::socket::shutdown_send, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + asio::error_code shutdown(shutdown_type what, + asio::error_code& ec) + { + return this->get_service().shutdown(this->get_implementation(), what, ec); + } + +protected: + /// Protected destructor to prevent deletion through this type. + ~basic_socket() + { + } +}; + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_BASIC_SOCKET_HPP diff --git a/asio-1.10.6/include/asio/basic_socket_acceptor.hpp b/asio-1.10.6/include/asio/basic_socket_acceptor.hpp new file mode 100644 index 0000000..4e3766d --- /dev/null +++ b/asio-1.10.6/include/asio/basic_socket_acceptor.hpp @@ -0,0 +1,1131 @@ +// +// basic_socket_acceptor.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_BASIC_SOCKET_ACCEPTOR_HPP +#define ASIO_BASIC_SOCKET_ACCEPTOR_HPP + + +#include "asio/detail/config.hpp" +#include "asio/basic_io_object.hpp" +#include "asio/basic_socket.hpp" +#include "asio/detail/handler_type_requirements.hpp" +#include "asio/detail/throw_error.hpp" +#include "asio/detail/type_traits.hpp" +#include "asio/error.hpp" +#include "asio/socket_acceptor_service.hpp" +#include "asio/socket_base.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +/// Provides the ability to accept new connections. +/** + * The basic_socket_acceptor class template is used for accepting new socket + * connections. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Example + * Opening a socket acceptor with the SO_REUSEADDR option enabled: + * @code + * asio::ip::tcp::acceptor acceptor(io_service); + * asio::ip::tcp::endpoint endpoint(asio::ip::tcp::v4(), port); + * acceptor.open(endpoint.protocol()); + * acceptor.set_option(asio::ip::tcp::acceptor::reuse_address(true)); + * acceptor.bind(endpoint); + * acceptor.listen(); + * @endcode + */ +template <typename Protocol, + typename SocketAcceptorService = socket_acceptor_service<Protocol> > +class basic_socket_acceptor + : public basic_io_object<SocketAcceptorService>, + public socket_base +{ +public: + /// (Deprecated: Use native_handle_type.) The native representation of an + /// acceptor. + typedef typename SocketAcceptorService::native_handle_type native_type; + + /// The native representation of an acceptor. + typedef typename SocketAcceptorService::native_handle_type native_handle_type; + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + /// Construct an acceptor without opening it. + /** + * This constructor creates an acceptor without opening it to listen for new + * connections. The open() function must be called before the acceptor can + * accept new socket connections. + * + * @param io_service The io_service object that the acceptor will use to + * dispatch handlers for any asynchronous operations performed on the + * acceptor. + */ + explicit basic_socket_acceptor(asio::io_service& io_service) + : basic_io_object<SocketAcceptorService>(io_service) + { + } + + /// Construct an open acceptor. + /** + * This constructor creates an acceptor and automatically opens it. + * + * @param io_service The io_service object that the acceptor will use to + * dispatch handlers for any asynchronous operations performed on the + * acceptor. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws asio::system_error Thrown on failure. + */ + basic_socket_acceptor(asio::io_service& io_service, + const protocol_type& protocol) + : basic_io_object<SocketAcceptorService>(io_service) + { + asio::error_code ec; + this->get_service().open(this->get_implementation(), protocol, ec); + asio::detail::throw_error(ec, "open"); + } + + /// Construct an acceptor opened on the given endpoint. + /** + * This constructor creates an acceptor and automatically opens it to listen + * for new connections on the specified endpoint. + * + * @param io_service The io_service object that the acceptor will use to + * dispatch handlers for any asynchronous operations performed on the + * acceptor. + * + * @param endpoint An endpoint on the local machine on which the acceptor + * will listen for new connections. + * + * @param reuse_addr Whether the constructor should set the socket option + * socket_base::reuse_address. + * + * @throws asio::system_error Thrown on failure. + * + * @note This constructor is equivalent to the following code: + * @code + * basic_socket_acceptor<Protocol> acceptor(io_service); + * acceptor.open(endpoint.protocol()); + * if (reuse_addr) + * acceptor.set_option(socket_base::reuse_address(true)); + * acceptor.bind(endpoint); + * acceptor.listen(listen_backlog); + * @endcode + */ + basic_socket_acceptor(asio::io_service& io_service, + const endpoint_type& endpoint, bool reuse_addr = true) + : basic_io_object<SocketAcceptorService>(io_service) + { + asio::error_code ec; + const protocol_type protocol = endpoint.protocol(); + this->get_service().open(this->get_implementation(), protocol, ec); + asio::detail::throw_error(ec, "open"); + if (reuse_addr) + { + this->get_service().set_option(this->get_implementation(), + socket_base::reuse_address(true), ec); + asio::detail::throw_error(ec, "set_option"); + } + this->get_service().bind(this->get_implementation(), endpoint, ec); + asio::detail::throw_error(ec, "bind"); + this->get_service().listen(this->get_implementation(), + socket_base::max_connections, ec); + asio::detail::throw_error(ec, "listen"); + } + + /// Construct a basic_socket_acceptor on an existing native acceptor. + /** + * This constructor creates an acceptor object to hold an existing native + * acceptor. + * + * @param io_service The io_service object that the acceptor will use to + * dispatch handlers for any asynchronous operations performed on the + * acceptor. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_acceptor A native acceptor. + * + * @throws asio::system_error Thrown on failure. + */ + basic_socket_acceptor(asio::io_service& io_service, + const protocol_type& protocol, const native_handle_type& native_acceptor) + : basic_io_object<SocketAcceptorService>(io_service) + { + asio::error_code ec; + this->get_service().assign(this->get_implementation(), + protocol, native_acceptor, ec); + asio::detail::throw_error(ec, "assign"); + } + + /// Move-construct a basic_socket_acceptor from another. + /** + * This constructor moves an acceptor from one object to another. + * + * @param other The other basic_socket_acceptor object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket_acceptor(io_service&) constructor. + */ + basic_socket_acceptor(basic_socket_acceptor&& other) + : basic_io_object<SocketAcceptorService>( + ASIO_MOVE_CAST(basic_socket_acceptor)(other)) + { + } + + /// Move-assign a basic_socket_acceptor from another. + /** + * This assignment operator moves an acceptor from one object to another. + * + * @param other The other basic_socket_acceptor object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket_acceptor(io_service&) constructor. + */ + basic_socket_acceptor& operator=(basic_socket_acceptor&& other) + { + basic_io_object<SocketAcceptorService>::operator=( + ASIO_MOVE_CAST(basic_socket_acceptor)(other)); + return *this; + } + + // All socket acceptors have access to each other's implementations. + template <typename Protocol1, typename SocketAcceptorService1> + friend class basic_socket_acceptor; + + /// Move-construct a basic_socket_acceptor from an acceptor of another + /// protocol type. + /** + * This constructor moves an acceptor from one object to another. + * + * @param other The other basic_socket_acceptor object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket(io_service&) constructor. + */ + template <typename Protocol1, typename SocketAcceptorService1> + basic_socket_acceptor( + basic_socket_acceptor<Protocol1, SocketAcceptorService1>&& other, + typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0) + : basic_io_object<SocketAcceptorService>(other.get_io_service()) + { + this->get_service().template converting_move_construct<Protocol1>( + this->get_implementation(), other.get_implementation()); + } + + /// Move-assign a basic_socket_acceptor from an acceptor of another protocol + /// type. + /** + * This assignment operator moves an acceptor from one object to another. + * + * @param other The other basic_socket_acceptor object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket(io_service&) constructor. + */ + template <typename Protocol1, typename SocketAcceptorService1> + typename enable_if<is_convertible<Protocol1, Protocol>::value, + basic_socket_acceptor>::type& operator=( + basic_socket_acceptor<Protocol1, SocketAcceptorService1>&& other) + { + basic_socket_acceptor tmp(ASIO_MOVE_CAST2(basic_socket_acceptor< + Protocol1, SocketAcceptorService1>)(other)); + basic_io_object<SocketAcceptorService>::operator=( + ASIO_MOVE_CAST(basic_socket_acceptor)(tmp)); + return *this; + } + + /// Open the acceptor using the specified protocol. + /** + * This function opens the socket acceptor so that it will use the specified + * protocol. + * + * @param protocol An object specifying which protocol is to be used. + * + * @throws asio::system_error Thrown on failure. + * + * @par Example + * @code + * asio::ip::tcp::acceptor acceptor(io_service); + * acceptor.open(asio::ip::tcp::v4()); + * @endcode + */ + void open(const protocol_type& protocol = protocol_type()) + { + asio::error_code ec; + this->get_service().open(this->get_implementation(), protocol, ec); + asio::detail::throw_error(ec, "open"); + } + + /// Open the acceptor using the specified protocol. + /** + * This function opens the socket acceptor so that it will use the specified + * protocol. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * asio::ip::tcp::acceptor acceptor(io_service); + * asio::error_code ec; + * acceptor.open(asio::ip::tcp::v4(), ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + asio::error_code open(const protocol_type& protocol, + asio::error_code& ec) + { + return this->get_service().open(this->get_implementation(), protocol, ec); + } + + /// Assigns an existing native acceptor to the acceptor. + /* + * This function opens the acceptor to hold an existing native acceptor. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param native_acceptor A native acceptor. + * + * @throws asio::system_error Thrown on failure. + */ + void assign(const protocol_type& protocol, + const native_handle_type& native_acceptor) + { + asio::error_code ec; + this->get_service().assign(this->get_implementation(), + protocol, native_acceptor, ec); + asio::detail::throw_error(ec, "assign"); + } + + /// Assigns an existing native acceptor to the acceptor. + /* + * This function opens the acceptor to hold an existing native acceptor. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param native_acceptor A native acceptor. + * + * @param ec Set to indicate what error occurred, if any. + */ + asio::error_code assign(const protocol_type& protocol, + const native_handle_type& native_acceptor, asio::error_code& ec) + { + return this->get_service().assign(this->get_implementation(), + protocol, native_acceptor, ec); + } + + /// Determine whether the acceptor is open. + bool is_open() const + { + return this->get_service().is_open(this->get_implementation()); + } + + /// Bind the acceptor to the given local endpoint. + /** + * This function binds the socket acceptor to the specified endpoint on the + * local machine. + * + * @param endpoint An endpoint on the local machine to which the socket + * acceptor will be bound. + * + * @throws asio::system_error Thrown on failure. + * + * @par Example + * @code + * asio::ip::tcp::acceptor acceptor(io_service); + * asio::ip::tcp::endpoint endpoint(asio::ip::tcp::v4(), 12345); + * acceptor.open(endpoint.protocol()); + * acceptor.bind(endpoint); + * @endcode + */ + void bind(const endpoint_type& endpoint) + { + asio::error_code ec; + this->get_service().bind(this->get_implementation(), endpoint, ec); + asio::detail::throw_error(ec, "bind"); + } + + /// Bind the acceptor to the given local endpoint. + /** + * This function binds the socket acceptor to the specified endpoint on the + * local machine. + * + * @param endpoint An endpoint on the local machine to which the socket + * acceptor will be bound. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * asio::ip::tcp::acceptor acceptor(io_service); + * asio::ip::tcp::endpoint endpoint(asio::ip::tcp::v4(), 12345); + * acceptor.open(endpoint.protocol()); + * asio::error_code ec; + * acceptor.bind(endpoint, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + asio::error_code bind(const endpoint_type& endpoint, + asio::error_code& ec) + { + return this->get_service().bind(this->get_implementation(), endpoint, ec); + } + + /// Place the acceptor into the state where it will listen for new + /// connections. + /** + * This function puts the socket acceptor into the state where it may accept + * new connections. + * + * @param backlog The maximum length of the queue of pending connections. + * + * @throws asio::system_error Thrown on failure. + */ + void listen(int backlog = socket_base::max_connections) + { + asio::error_code ec; + this->get_service().listen(this->get_implementation(), backlog, ec); + asio::detail::throw_error(ec, "listen"); + } + + /// Place the acceptor into the state where it will listen for new + /// connections. + /** + * This function puts the socket acceptor into the state where it may accept + * new connections. + * + * @param backlog The maximum length of the queue of pending connections. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * asio::ip::tcp::acceptor acceptor(io_service); + * ... + * asio::error_code ec; + * acceptor.listen(asio::socket_base::max_connections, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + asio::error_code listen(int backlog, asio::error_code& ec) + { + return this->get_service().listen(this->get_implementation(), backlog, ec); + } + + /// Close the acceptor. + /** + * This function is used to close the acceptor. Any asynchronous accept + * operations will be cancelled immediately. + * + * A subsequent call to open() is required before the acceptor can again be + * used to again perform socket accept operations. + * + * @throws asio::system_error Thrown on failure. + */ + void close() + { + asio::error_code ec; + this->get_service().close(this->get_implementation(), ec); + asio::detail::throw_error(ec, "close"); + } + + /// Close the acceptor. + /** + * This function is used to close the acceptor. Any asynchronous accept + * operations will be cancelled immediately. + * + * A subsequent call to open() is required before the acceptor can again be + * used to again perform socket accept operations. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * asio::ip::tcp::acceptor acceptor(io_service); + * ... + * asio::error_code ec; + * acceptor.close(ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + asio::error_code close(asio::error_code& ec) + { + return this->get_service().close(this->get_implementation(), ec); + } + + /// (Deprecated: Use native_handle().) Get the native acceptor representation. + /** + * This function may be used to obtain the underlying representation of the + * acceptor. This is intended to allow access to native acceptor functionality + * that is not otherwise provided. + */ + native_type native() + { + return this->get_service().native_handle(this->get_implementation()); + } + + /// Get the native acceptor representation. + /** + * This function may be used to obtain the underlying representation of the + * acceptor. This is intended to allow access to native acceptor functionality + * that is not otherwise provided. + */ + native_handle_type native_handle() + { + return this->get_service().native_handle(this->get_implementation()); + } + + /// Cancel all asynchronous operations associated with the acceptor. + /** + * This function causes all outstanding asynchronous connect, send and receive + * operations to finish immediately, and the handlers for cancelled operations + * will be passed the asio::error::operation_aborted error. + * + * @throws asio::system_error Thrown on failure. + */ + void cancel() + { + asio::error_code ec; + this->get_service().cancel(this->get_implementation(), ec); + asio::detail::throw_error(ec, "cancel"); + } + + /// Cancel all asynchronous operations associated with the acceptor. + /** + * This function causes all outstanding asynchronous connect, send and receive + * operations to finish immediately, and the handlers for cancelled operations + * will be passed the asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + asio::error_code cancel(asio::error_code& ec) + { + return this->get_service().cancel(this->get_implementation(), ec); + } + + /// Set an option on the acceptor. + /** + * This function is used to set an option on the acceptor. + * + * @param option The new option value to be set on the acceptor. + * + * @throws asio::system_error Thrown on failure. + * + * @sa SettableSocketOption @n + * asio::socket_base::reuse_address + * asio::socket_base::enable_connection_aborted + * + * @par Example + * Setting the SOL_SOCKET/SO_REUSEADDR option: + * @code + * asio::ip::tcp::acceptor acceptor(io_service); + * ... + * asio::ip::tcp::acceptor::reuse_address option(true); + * acceptor.set_option(option); + * @endcode + */ + template <typename SettableSocketOption> + void set_option(const SettableSocketOption& option) + { + asio::error_code ec; + this->get_service().set_option(this->get_implementation(), option, ec); + asio::detail::throw_error(ec, "set_option"); + } + + /// Set an option on the acceptor. + /** + * This function is used to set an option on the acceptor. + * + * @param option The new option value to be set on the acceptor. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa SettableSocketOption @n + * asio::socket_base::reuse_address + * asio::socket_base::enable_connection_aborted + * + * @par Example + * Setting the SOL_SOCKET/SO_REUSEADDR option: + * @code + * asio::ip::tcp::acceptor acceptor(io_service); + * ... + * asio::ip::tcp::acceptor::reuse_address option(true); + * asio::error_code ec; + * acceptor.set_option(option, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template <typename SettableSocketOption> + asio::error_code set_option(const SettableSocketOption& option, + asio::error_code& ec) + { + return this->get_service().set_option( + this->get_implementation(), option, ec); + } + + /// Get an option from the acceptor. + /** + * This function is used to get the current value of an option on the + * acceptor. + * + * @param option The option value to be obtained from the acceptor. + * + * @throws asio::system_error Thrown on failure. + * + * @sa GettableSocketOption @n + * asio::socket_base::reuse_address + * + * @par Example + * Getting the value of the SOL_SOCKET/SO_REUSEADDR option: + * @code + * asio::ip::tcp::acceptor acceptor(io_service); + * ... + * asio::ip::tcp::acceptor::reuse_address option; + * acceptor.get_option(option); + * bool is_set = option.get(); + * @endcode + */ + template <typename GettableSocketOption> + void get_option(GettableSocketOption& option) + { + asio::error_code ec; + this->get_service().get_option(this->get_implementation(), option, ec); + asio::detail::throw_error(ec, "get_option"); + } + + /// Get an option from the acceptor. + /** + * This function is used to get the current value of an option on the + * acceptor. + * + * @param option The option value to be obtained from the acceptor. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa GettableSocketOption @n + * asio::socket_base::reuse_address + * + * @par Example + * Getting the value of the SOL_SOCKET/SO_REUSEADDR option: + * @code + * asio::ip::tcp::acceptor acceptor(io_service); + * ... + * asio::ip::tcp::acceptor::reuse_address option; + * asio::error_code ec; + * acceptor.get_option(option, ec); + * if (ec) + * { + * // An error occurred. + * } + * bool is_set = option.get(); + * @endcode + */ + template <typename GettableSocketOption> + asio::error_code get_option(GettableSocketOption& option, + asio::error_code& ec) + { + return this->get_service().get_option( + this->get_implementation(), option, ec); + } + + /// Perform an IO control command on the acceptor. + /** + * This function is used to execute an IO control command on the acceptor. + * + * @param command The IO control command to be performed on the acceptor. + * + * @throws asio::system_error Thrown on failure. + * + * @sa IoControlCommand @n + * asio::socket_base::non_blocking_io + * + * @par Example + * Getting the number of bytes ready to read: + * @code + * asio::ip::tcp::acceptor acceptor(io_service); + * ... + * asio::ip::tcp::acceptor::non_blocking_io command(true); + * socket.io_control(command); + * @endcode + */ + template <typename IoControlCommand> + void io_control(IoControlCommand& command) + { + asio::error_code ec; + this->get_service().io_control(this->get_implementation(), command, ec); + asio::detail::throw_error(ec, "io_control"); + } + + /// Perform an IO control command on the acceptor. + /** + * This function is used to execute an IO control command on the acceptor. + * + * @param command The IO control command to be performed on the acceptor. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa IoControlCommand @n + * asio::socket_base::non_blocking_io + * + * @par Example + * Getting the number of bytes ready to read: + * @code + * asio::ip::tcp::acceptor acceptor(io_service); + * ... + * asio::ip::tcp::acceptor::non_blocking_io command(true); + * asio::error_code ec; + * socket.io_control(command, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template <typename IoControlCommand> + asio::error_code io_control(IoControlCommand& command, + asio::error_code& ec) + { + return this->get_service().io_control( + this->get_implementation(), command, ec); + } + + /// Gets the non-blocking mode of the acceptor. + /** + * @returns @c true if the acceptor's synchronous operations will fail with + * asio::error::would_block if they are unable to perform the requested + * operation immediately. If @c false, synchronous operations will block + * until complete. + * + * @note The non-blocking mode has no effect on the behaviour of asynchronous + * operations. Asynchronous operations will never fail with the error + * asio::error::would_block. + */ + bool non_blocking() const + { + return this->get_service().non_blocking(this->get_implementation()); + } + + /// Sets the non-blocking mode of the acceptor. + /** + * @param mode If @c true, the acceptor's synchronous operations will fail + * with asio::error::would_block if they are unable to perform the + * requested operation immediately. If @c false, synchronous operations will + * block until complete. + * + * @throws asio::system_error Thrown on failure. + * + * @note The non-blocking mode has no effect on the behaviour of asynchronous + * operations. Asynchronous operations will never fail with the error + * asio::error::would_block. + */ + void non_blocking(bool mode) + { + asio::error_code ec; + this->get_service().non_blocking(this->get_implementation(), mode, ec); + asio::detail::throw_error(ec, "non_blocking"); + } + + /// Sets the non-blocking mode of the acceptor. + /** + * @param mode If @c true, the acceptor's synchronous operations will fail + * with asio::error::would_block if they are unable to perform the + * requested operation immediately. If @c false, synchronous operations will + * block until complete. + * + * @param ec Set to indicate what error occurred, if any. + * + * @note The non-blocking mode has no effect on the behaviour of asynchronous + * operations. Asynchronous operations will never fail with the error + * asio::error::would_block. + */ + asio::error_code non_blocking( + bool mode, asio::error_code& ec) + { + return this->get_service().non_blocking( + this->get_implementation(), mode, ec); + } + + /// Gets the non-blocking mode of the native acceptor implementation. + /** + * This function is used to retrieve the non-blocking mode of the underlying + * native acceptor. This mode has no effect on the behaviour of the acceptor + * object's synchronous operations. + * + * @returns @c true if the underlying acceptor is in non-blocking mode and + * direct system calls may fail with asio::error::would_block (or the + * equivalent system error). + * + * @note The current non-blocking mode is cached by the acceptor object. + * Consequently, the return value may be incorrect if the non-blocking mode + * was set directly on the native acceptor. + */ + bool native_non_blocking() const + { + return this->get_service().native_non_blocking(this->get_implementation()); + } + + /// Sets the non-blocking mode of the native acceptor implementation. + /** + * This function is used to modify the non-blocking mode of the underlying + * native acceptor. It has no effect on the behaviour of the acceptor object's + * synchronous operations. + * + * @param mode If @c true, the underlying acceptor is put into non-blocking + * mode and direct system calls may fail with asio::error::would_block + * (or the equivalent system error). + * + * @throws asio::system_error Thrown on failure. If the @c mode is + * @c false, but the current value of @c non_blocking() is @c true, this + * function fails with asio::error::invalid_argument, as the + * combination does not make sense. + */ + void native_non_blocking(bool mode) + { + asio::error_code ec; + this->get_service().native_non_blocking( + this->get_implementation(), mode, ec); + asio::detail::throw_error(ec, "native_non_blocking"); + } + + /// Sets the non-blocking mode of the native acceptor implementation. + /** + * This function is used to modify the non-blocking mode of the underlying + * native acceptor. It has no effect on the behaviour of the acceptor object's + * synchronous operations. + * + * @param mode If @c true, the underlying acceptor is put into non-blocking + * mode and direct system calls may fail with asio::error::would_block + * (or the equivalent system error). + * + * @param ec Set to indicate what error occurred, if any. If the @c mode is + * @c false, but the current value of @c non_blocking() is @c true, this + * function fails with asio::error::invalid_argument, as the + * combination does not make sense. + */ + asio::error_code native_non_blocking( + bool mode, asio::error_code& ec) + { + return this->get_service().native_non_blocking( + this->get_implementation(), mode, ec); + } + + /// Get the local endpoint of the acceptor. + /** + * This function is used to obtain the locally bound endpoint of the acceptor. + * + * @returns An object that represents the local endpoint of the acceptor. + * + * @throws asio::system_error Thrown on failure. + * + * @par Example + * @code + * asio::ip::tcp::acceptor acceptor(io_service); + * ... + * asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(); + * @endcode + */ + endpoint_type local_endpoint() const + { + asio::error_code ec; + endpoint_type ep = this->get_service().local_endpoint( + this->get_implementation(), ec); + asio::detail::throw_error(ec, "local_endpoint"); + return ep; + } + + /// Get the local endpoint of the acceptor. + /** + * This function is used to obtain the locally bound endpoint of the acceptor. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns An object that represents the local endpoint of the acceptor. + * Returns a default-constructed endpoint object if an error occurred and the + * error handler did not throw an exception. + * + * @par Example + * @code + * asio::ip::tcp::acceptor acceptor(io_service); + * ... + * asio::error_code ec; + * asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + endpoint_type local_endpoint(asio::error_code& ec) const + { + return this->get_service().local_endpoint(this->get_implementation(), ec); + } + + /// Accept a new connection. + /** + * This function is used to accept a new connection from a peer into the + * given socket. The function call will block until a new connection has been + * accepted successfully or an error occurs. + * + * @param peer The socket into which the new connection will be accepted. + * + * @throws asio::system_error Thrown on failure. + * + * @par Example + * @code + * asio::ip::tcp::acceptor acceptor(io_service); + * ... + * asio::ip::tcp::socket socket(io_service); + * acceptor.accept(socket); + * @endcode + */ + template <typename Protocol1, typename SocketService> + void accept(basic_socket<Protocol1, SocketService>& peer, + typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0) + { + asio::error_code ec; + this->get_service().accept(this->get_implementation(), + peer, static_cast<endpoint_type*>(0), ec); + asio::detail::throw_error(ec, "accept"); + } + + /// Accept a new connection. + /** + * This function is used to accept a new connection from a peer into the + * given socket. The function call will block until a new connection has been + * accepted successfully or an error occurs. + * + * @param peer The socket into which the new connection will be accepted. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * asio::ip::tcp::acceptor acceptor(io_service); + * ... + * asio::ip::tcp::soocket socket(io_service); + * asio::error_code ec; + * acceptor.accept(socket, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template <typename Protocol1, typename SocketService> + asio::error_code accept( + basic_socket<Protocol1, SocketService>& peer, + asio::error_code& ec, + typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0) + { + return this->get_service().accept(this->get_implementation(), + peer, static_cast<endpoint_type*>(0), ec); + } + + /// Start an asynchronous accept. + /** + * This function is used to asynchronously accept a new connection into a + * socket. The function call always returns immediately. + * + * @param peer The socket into which the new connection will be accepted. + * Ownership of the peer object is retained by the caller, which must + * guarantee that it is valid until the handler is called. + * + * @param handler The handler to be called when the accept operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const asio::error_code& error // Result of operation. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @par Example + * @code + * void accept_handler(const asio::error_code& error) + * { + * if (!error) + * { + * // Accept succeeded. + * } + * } + * + * ... + * + * asio::ip::tcp::acceptor acceptor(io_service); + * ... + * asio::ip::tcp::socket socket(io_service); + * acceptor.async_accept(socket, accept_handler); + * @endcode + */ + template <typename Protocol1, typename SocketService, typename AcceptHandler> + ASIO_INITFN_RESULT_TYPE(AcceptHandler, + void (asio::error_code)) + async_accept(basic_socket<Protocol1, SocketService>& peer, + ASIO_MOVE_ARG(AcceptHandler) handler, + typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a AcceptHandler. + ASIO_ACCEPT_HANDLER_CHECK(AcceptHandler, handler) type_check; + + return this->get_service().async_accept(this->get_implementation(), + peer, static_cast<endpoint_type*>(0), + ASIO_MOVE_CAST(AcceptHandler)(handler)); + } + + /// Accept a new connection and obtain the endpoint of the peer + /** + * This function is used to accept a new connection from a peer into the + * given socket, and additionally provide the endpoint of the remote peer. + * The function call will block until a new connection has been accepted + * successfully or an error occurs. + * + * @param peer The socket into which the new connection will be accepted. + * + * @param peer_endpoint An endpoint object which will receive the endpoint of + * the remote peer. + * + * @throws asio::system_error Thrown on failure. + * + * @par Example + * @code + * asio::ip::tcp::acceptor acceptor(io_service); + * ... + * asio::ip::tcp::socket socket(io_service); + * asio::ip::tcp::endpoint endpoint; + * acceptor.accept(socket, endpoint); + * @endcode + */ + template <typename SocketService> + void accept(basic_socket<protocol_type, SocketService>& peer, + endpoint_type& peer_endpoint) + { + asio::error_code ec; + this->get_service().accept(this->get_implementation(), + peer, &peer_endpoint, ec); + asio::detail::throw_error(ec, "accept"); + } + + /// Accept a new connection and obtain the endpoint of the peer + /** + * This function is used to accept a new connection from a peer into the + * given socket, and additionally provide the endpoint of the remote peer. + * The function call will block until a new connection has been accepted + * successfully or an error occurs. + * + * @param peer The socket into which the new connection will be accepted. + * + * @param peer_endpoint An endpoint object which will receive the endpoint of + * the remote peer. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * asio::ip::tcp::acceptor acceptor(io_service); + * ... + * asio::ip::tcp::socket socket(io_service); + * asio::ip::tcp::endpoint endpoint; + * asio::error_code ec; + * acceptor.accept(socket, endpoint, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template <typename SocketService> + asio::error_code accept( + basic_socket<protocol_type, SocketService>& peer, + endpoint_type& peer_endpoint, asio::error_code& ec) + { + return this->get_service().accept( + this->get_implementation(), peer, &peer_endpoint, ec); + } + + /// Start an asynchronous accept. + /** + * This function is used to asynchronously accept a new connection into a + * socket, and additionally obtain the endpoint of the remote peer. The + * function call always returns immediately. + * + * @param peer The socket into which the new connection will be accepted. + * Ownership of the peer object is retained by the caller, which must + * guarantee that it is valid until the handler is called. + * + * @param peer_endpoint An endpoint object into which the endpoint of the + * remote peer will be written. Ownership of the peer_endpoint object is + * retained by the caller, which must guarantee that it is valid until the + * handler is called. + * + * @param handler The handler to be called when the accept operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const asio::error_code& error // Result of operation. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + */ + template <typename SocketService, typename AcceptHandler> + ASIO_INITFN_RESULT_TYPE(AcceptHandler, + void (asio::error_code)) + async_accept(basic_socket<protocol_type, SocketService>& peer, + endpoint_type& peer_endpoint, ASIO_MOVE_ARG(AcceptHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a AcceptHandler. + ASIO_ACCEPT_HANDLER_CHECK(AcceptHandler, handler) type_check; + + return this->get_service().async_accept(this->get_implementation(), peer, + &peer_endpoint, ASIO_MOVE_CAST(AcceptHandler)(handler)); + } +}; + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_BASIC_SOCKET_ACCEPTOR_HPP diff --git a/asio-1.10.6/include/asio/basic_socket_iostream.hpp b/asio-1.10.6/include/asio/basic_socket_iostream.hpp new file mode 100644 index 0000000..13a4bdd --- /dev/null +++ b/asio-1.10.6/include/asio/basic_socket_iostream.hpp @@ -0,0 +1,18 @@ +// +// basic_socket_iostream.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_BASIC_SOCKET_IOSTREAM_HPP +#define ASIO_BASIC_SOCKET_IOSTREAM_HPP + + +#include "asio/detail/config.hpp" + + +#endif // ASIO_BASIC_SOCKET_IOSTREAM_HPP diff --git a/asio-1.10.6/include/asio/basic_stream_socket.hpp b/asio-1.10.6/include/asio/basic_stream_socket.hpp new file mode 100644 index 0000000..e2f38da --- /dev/null +++ b/asio-1.10.6/include/asio/basic_stream_socket.hpp @@ -0,0 +1,847 @@ +// +// basic_stream_socket.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_BASIC_STREAM_SOCKET_HPP +#define ASIO_BASIC_STREAM_SOCKET_HPP + + +#include "asio/detail/config.hpp" +#include <cstddef> +#include "asio/async_result.hpp" +#include "asio/basic_socket.hpp" +#include "asio/detail/handler_type_requirements.hpp" +#include "asio/detail/throw_error.hpp" +#include "asio/error.hpp" +#include "asio/stream_socket_service.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +/// Provides stream-oriented socket functionality. +/** + * The basic_stream_socket class template provides asynchronous and blocking + * stream-oriented socket functionality. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Concepts: + * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. + */ +template <typename Protocol, + typename StreamSocketService = stream_socket_service<Protocol> > +class basic_stream_socket + : public basic_socket<Protocol, StreamSocketService> +{ +public: + /// (Deprecated: Use native_handle_type.) The native representation of a + /// socket. + typedef typename StreamSocketService::native_handle_type native_type; + + /// The native representation of a socket. + typedef typename StreamSocketService::native_handle_type native_handle_type; + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + /// Construct a basic_stream_socket without opening it. + /** + * This constructor creates a stream socket without opening it. The socket + * needs to be opened and then connected or accepted before data can be sent + * or received on it. + * + * @param io_service The io_service object that the stream socket will use to + * dispatch handlers for any asynchronous operations performed on the socket. + */ + explicit basic_stream_socket(asio::io_service& io_service) + : basic_socket<Protocol, StreamSocketService>(io_service) + { + } + + /// Construct and open a basic_stream_socket. + /** + * This constructor creates and opens a stream socket. The socket needs to be + * connected or accepted before data can be sent or received on it. + * + * @param io_service The io_service object that the stream socket will use to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws asio::system_error Thrown on failure. + */ + basic_stream_socket(asio::io_service& io_service, + const protocol_type& protocol) + : basic_socket<Protocol, StreamSocketService>(io_service, protocol) + { + } + + /// Construct a basic_stream_socket, opening it and binding it to the given + /// local endpoint. + /** + * This constructor creates a stream socket and automatically opens it bound + * to the specified endpoint on the local machine. The protocol used is the + * protocol associated with the given endpoint. + * + * @param io_service The io_service object that the stream socket will use to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param endpoint An endpoint on the local machine to which the stream + * socket will be bound. + * + * @throws asio::system_error Thrown on failure. + */ + basic_stream_socket(asio::io_service& io_service, + const endpoint_type& endpoint) + : basic_socket<Protocol, StreamSocketService>(io_service, endpoint) + { + } + + /// Construct a basic_stream_socket on an existing native socket. + /** + * This constructor creates a stream socket object to hold an existing native + * socket. + * + * @param io_service The io_service object that the stream socket will use to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_socket The new underlying socket implementation. + * + * @throws asio::system_error Thrown on failure. + */ + basic_stream_socket(asio::io_service& io_service, + const protocol_type& protocol, const native_handle_type& native_socket) + : basic_socket<Protocol, StreamSocketService>( + io_service, protocol, native_socket) + { + } + + /// Move-construct a basic_stream_socket from another. + /** + * This constructor moves a stream socket from one object to another. + * + * @param other The other basic_stream_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_stream_socket(io_service&) constructor. + */ + basic_stream_socket(basic_stream_socket&& other) + : basic_socket<Protocol, StreamSocketService>( + ASIO_MOVE_CAST(basic_stream_socket)(other)) + { + } + + /// Move-assign a basic_stream_socket from another. + /** + * This assignment operator moves a stream socket from one object to another. + * + * @param other The other basic_stream_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_stream_socket(io_service&) constructor. + */ + basic_stream_socket& operator=(basic_stream_socket&& other) + { + basic_socket<Protocol, StreamSocketService>::operator=( + ASIO_MOVE_CAST(basic_stream_socket)(other)); + return *this; + } + + /// Move-construct a basic_stream_socket from a socket of another protocol + /// type. + /** + * This constructor moves a stream socket from one object to another. + * + * @param other The other basic_stream_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_stream_socket(io_service&) constructor. + */ + template <typename Protocol1, typename StreamSocketService1> + basic_stream_socket( + basic_stream_socket<Protocol1, StreamSocketService1>&& other, + typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0) + : basic_socket<Protocol, StreamSocketService>( + ASIO_MOVE_CAST2(basic_stream_socket< + Protocol1, StreamSocketService1>)(other)) + { + } + + /// Move-assign a basic_stream_socket from a socket of another protocol type. + /** + * This assignment operator moves a stream socket from one object to another. + * + * @param other The other basic_stream_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_stream_socket(io_service&) constructor. + */ + template <typename Protocol1, typename StreamSocketService1> + typename enable_if<is_convertible<Protocol1, Protocol>::value, + basic_stream_socket>::type& operator=( + basic_stream_socket<Protocol1, StreamSocketService1>&& other) + { + basic_socket<Protocol, StreamSocketService>::operator=( + ASIO_MOVE_CAST2(basic_stream_socket< + Protocol1, StreamSocketService1>)(other)); + return *this; + } + + /// Send some data on the socket. + /** + * This function is used to send data on the stream socket. The function + * call will block until one or more bytes of the data has been sent + * successfully, or an until error occurs. + * + * @param buffers One or more data buffers to be sent on the socket. + * + * @returns The number of bytes sent. + * + * @throws asio::system_error Thrown on failure. + * + * @note The send operation may not transmit all of the data to the peer. + * Consider using the @ref write function if you need to ensure that all data + * is written before the blocking operation completes. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * socket.send(asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence> + std::size_t send(const ConstBufferSequence& buffers) + { + asio::error_code ec; + std::size_t s = this->get_service().send( + this->get_implementation(), buffers, 0, ec); + asio::detail::throw_error(ec, "send"); + return s; + } + + /// Send some data on the socket. + /** + * This function is used to send data on the stream socket. The function + * call will block until one or more bytes of the data has been sent + * successfully, or an until error occurs. + * + * @param buffers One or more data buffers to be sent on the socket. + * + * @param flags Flags specifying how the send call is to be made. + * + * @returns The number of bytes sent. + * + * @throws asio::system_error Thrown on failure. + * + * @note The send operation may not transmit all of the data to the peer. + * Consider using the @ref write function if you need to ensure that all data + * is written before the blocking operation completes. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * socket.send(asio::buffer(data, size), 0); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence> + std::size_t send(const ConstBufferSequence& buffers, + socket_base::message_flags flags) + { + asio::error_code ec; + std::size_t s = this->get_service().send( + this->get_implementation(), buffers, flags, ec); + asio::detail::throw_error(ec, "send"); + return s; + } + + /// Send some data on the socket. + /** + * This function is used to send data on the stream socket. The function + * call will block until one or more bytes of the data has been sent + * successfully, or an until error occurs. + * + * @param buffers One or more data buffers to be sent on the socket. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes sent. Returns 0 if an error occurred. + * + * @note The send operation may not transmit all of the data to the peer. + * Consider using the @ref write function if you need to ensure that all data + * is written before the blocking operation completes. + */ + template <typename ConstBufferSequence> + std::size_t send(const ConstBufferSequence& buffers, + socket_base::message_flags flags, asio::error_code& ec) + { + return this->get_service().send( + this->get_implementation(), buffers, flags, ec); + } + + /// Start an asynchronous send. + /** + * This function is used to asynchronously send data on the stream socket. + * The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent on the socket. Although + * the buffers object may be copied as necessary, ownership of the underlying + * memory blocks is retained by the caller, which must guarantee that they + * remain valid until the handler is called. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note The send operation may not transmit all of the data to the peer. + * Consider using the @ref async_write function if you need to ensure that all + * data is written before the asynchronous operation completes. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * socket.async_send(asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence, typename WriteHandler> + ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (asio::error_code, std::size_t)) + async_send(const ConstBufferSequence& buffers, + ASIO_MOVE_ARG(WriteHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a WriteHandler. + ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + return this->get_service().async_send( + this->get_implementation(), buffers, 0, + ASIO_MOVE_CAST(WriteHandler)(handler)); + } + + /// Start an asynchronous send. + /** + * This function is used to asynchronously send data on the stream socket. + * The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent on the socket. Although + * the buffers object may be copied as necessary, ownership of the underlying + * memory blocks is retained by the caller, which must guarantee that they + * remain valid until the handler is called. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note The send operation may not transmit all of the data to the peer. + * Consider using the @ref async_write function if you need to ensure that all + * data is written before the asynchronous operation completes. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * socket.async_send(asio::buffer(data, size), 0, handler); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence, typename WriteHandler> + ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (asio::error_code, std::size_t)) + async_send(const ConstBufferSequence& buffers, + socket_base::message_flags flags, + ASIO_MOVE_ARG(WriteHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a WriteHandler. + ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + return this->get_service().async_send( + this->get_implementation(), buffers, flags, + ASIO_MOVE_CAST(WriteHandler)(handler)); + } + + /// Receive some data on the socket. + /** + * This function is used to receive data on the stream socket. The function + * call will block until one or more bytes of data has been received + * successfully, or until an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @returns The number of bytes received. + * + * @throws asio::system_error Thrown on failure. An error code of + * asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The receive operation may not receive all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that the + * requested amount of data is read before the blocking operation completes. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.receive(asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence> + std::size_t receive(const MutableBufferSequence& buffers) + { + asio::error_code ec; + std::size_t s = this->get_service().receive( + this->get_implementation(), buffers, 0, ec); + asio::detail::throw_error(ec, "receive"); + return s; + } + + /// Receive some data on the socket. + /** + * This function is used to receive data on the stream socket. The function + * call will block until one or more bytes of data has been received + * successfully, or until an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @returns The number of bytes received. + * + * @throws asio::system_error Thrown on failure. An error code of + * asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The receive operation may not receive all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that the + * requested amount of data is read before the blocking operation completes. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.receive(asio::buffer(data, size), 0); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence> + std::size_t receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags) + { + asio::error_code ec; + std::size_t s = this->get_service().receive( + this->get_implementation(), buffers, flags, ec); + asio::detail::throw_error(ec, "receive"); + return s; + } + + /// Receive some data on a connected socket. + /** + * This function is used to receive data on the stream socket. The function + * call will block until one or more bytes of data has been received + * successfully, or until an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes received. Returns 0 if an error occurred. + * + * @note The receive operation may not receive all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that the + * requested amount of data is read before the blocking operation completes. + */ + template <typename MutableBufferSequence> + std::size_t receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags, asio::error_code& ec) + { + return this->get_service().receive( + this->get_implementation(), buffers, flags, ec); + } + + /// Start an asynchronous receive. + /** + * This function is used to asynchronously receive data from the stream + * socket. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note The receive operation may not receive all of the requested number of + * bytes. Consider using the @ref async_read function if you need to ensure + * that the requested amount of data is received before the asynchronous + * operation completes. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.async_receive(asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence, typename ReadHandler> + ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (asio::error_code, std::size_t)) + async_receive(const MutableBufferSequence& buffers, + ASIO_MOVE_ARG(ReadHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + return this->get_service().async_receive(this->get_implementation(), + buffers, 0, ASIO_MOVE_CAST(ReadHandler)(handler)); + } + + /// Start an asynchronous receive. + /** + * This function is used to asynchronously receive data from the stream + * socket. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note The receive operation may not receive all of the requested number of + * bytes. Consider using the @ref async_read function if you need to ensure + * that the requested amount of data is received before the asynchronous + * operation completes. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.async_receive(asio::buffer(data, size), 0, handler); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence, typename ReadHandler> + ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (asio::error_code, std::size_t)) + async_receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags, + ASIO_MOVE_ARG(ReadHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + return this->get_service().async_receive(this->get_implementation(), + buffers, flags, ASIO_MOVE_CAST(ReadHandler)(handler)); + } + + /// Write some data to the socket. + /** + * This function is used to write data to the stream socket. The function call + * will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the socket. + * + * @returns The number of bytes written. + * + * @throws asio::system_error Thrown on failure. An error code of + * asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * socket.write_some(asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence> + std::size_t write_some(const ConstBufferSequence& buffers) + { + asio::error_code ec; + std::size_t s = this->get_service().send( + this->get_implementation(), buffers, 0, ec); + asio::detail::throw_error(ec, "write_some"); + return s; + } + + /// Write some data to the socket. + /** + * This function is used to write data to the stream socket. The function call + * will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. Returns 0 if an error occurred. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + */ + template <typename ConstBufferSequence> + std::size_t write_some(const ConstBufferSequence& buffers, + asio::error_code& ec) + { + return this->get_service().send(this->get_implementation(), buffers, 0, ec); + } + + /// Start an asynchronous write. + /** + * This function is used to asynchronously write data to the stream socket. + * The function call always returns immediately. + * + * @param buffers One or more data buffers to be written to the socket. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes written. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note The write operation may not transmit all of the data to the peer. + * Consider using the @ref async_write function if you need to ensure that all + * data is written before the asynchronous operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * socket.async_write_some(asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence, typename WriteHandler> + ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (asio::error_code, std::size_t)) + async_write_some(const ConstBufferSequence& buffers, + ASIO_MOVE_ARG(WriteHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a WriteHandler. + ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + return this->get_service().async_send(this->get_implementation(), + buffers, 0, ASIO_MOVE_CAST(WriteHandler)(handler)); + } + + /// Read some data from the socket. + /** + * This function is used to read data from the stream socket. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @returns The number of bytes read. + * + * @throws asio::system_error Thrown on failure. An error code of + * asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * socket.read_some(asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence> + std::size_t read_some(const MutableBufferSequence& buffers) + { + asio::error_code ec; + std::size_t s = this->get_service().receive( + this->get_implementation(), buffers, 0, ec); + asio::detail::throw_error(ec, "read_some"); + return s; + } + + /// Read some data from the socket. + /** + * This function is used to read data from the stream socket. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. Returns 0 if an error occurred. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + */ + template <typename MutableBufferSequence> + std::size_t read_some(const MutableBufferSequence& buffers, + asio::error_code& ec) + { + return this->get_service().receive( + this->get_implementation(), buffers, 0, ec); + } + + /// Start an asynchronous read. + /** + * This function is used to asynchronously read data from the stream socket. + * The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be read. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes read. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note The read operation may not read all of the requested number of bytes. + * Consider using the @ref async_read function if you need to ensure that the + * requested amount of data is read before the asynchronous operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * socket.async_read_some(asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence, typename ReadHandler> + ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (asio::error_code, std::size_t)) + async_read_some(const MutableBufferSequence& buffers, + ASIO_MOVE_ARG(ReadHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + return this->get_service().async_receive(this->get_implementation(), + buffers, 0, ASIO_MOVE_CAST(ReadHandler)(handler)); + } +}; + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_BASIC_STREAM_SOCKET_HPP diff --git a/asio-1.10.6/include/asio/basic_streambuf_fwd.hpp b/asio-1.10.6/include/asio/basic_streambuf_fwd.hpp new file mode 100644 index 0000000..bbe37dc --- /dev/null +++ b/asio-1.10.6/include/asio/basic_streambuf_fwd.hpp @@ -0,0 +1,18 @@ +// +// basic_streambuf_fwd.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_BASIC_STREAMBUF_FWD_HPP +#define ASIO_BASIC_STREAMBUF_FWD_HPP + + +#include "asio/detail/config.hpp" + + +#endif // ASIO_BASIC_STREAMBUF_FWD_HPP diff --git a/asio-1.10.6/include/asio/buffer.hpp b/asio-1.10.6/include/asio/buffer.hpp new file mode 100644 index 0000000..e29dc25 --- /dev/null +++ b/asio-1.10.6/include/asio/buffer.hpp @@ -0,0 +1,2087 @@ +// +// buffer.hpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_BUFFER_HPP +#define ASIO_BUFFER_HPP + + +#include "asio/detail/config.hpp" +#include <cstddef> +#include <cstring> +#include <string> +#include <vector> +#include "asio/detail/array_fwd.hpp" + + +#if defined(__GNUC__) +# if defined(_GLIBCXX_DEBUG) +# endif // defined(_GLIBCXX_DEBUG) +#endif // defined(__GNUC__) + + + +#if defined(ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND) +# include "asio/detail/type_traits.hpp" +#endif // defined(ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND) + +#include "asio/detail/push_options.hpp" + +namespace asio { + +class mutable_buffer; +class const_buffer; + +namespace detail { +void* buffer_cast_helper(const mutable_buffer&); +const void* buffer_cast_helper(const const_buffer&); +std::size_t buffer_size_helper(const mutable_buffer&); +std::size_t buffer_size_helper(const const_buffer&); +} // namespace detail + +/// Holds a buffer that can be modified. +/** + * The mutable_buffer class provides a safe representation of a buffer that can + * be modified. It does not own the underlying data, and so is cheap to copy or + * assign. + * + * @par Accessing Buffer Contents + * + * The contents of a buffer may be accessed using the @ref buffer_size + * and @ref buffer_cast functions: + * + * @code asio::mutable_buffer b1 = ...; + * std::size_t s1 = asio::buffer_size(b1); + * unsigned char* p1 = asio::buffer_cast<unsigned char*>(b1); + * @endcode + * + * The asio::buffer_cast function permits violations of type safety, so + * uses of it in application code should be carefully considered. + */ +class mutable_buffer +{ +public: + /// Construct an empty buffer. + mutable_buffer() + : data_(0), + size_(0) + { + } + + /// Construct a buffer to represent a given memory range. + mutable_buffer(void* data, std::size_t size) + : data_(data), + size_(size) + { + } + + +private: + friend void* asio::detail::buffer_cast_helper( + const mutable_buffer& b); + friend std::size_t asio::detail::buffer_size_helper( + const mutable_buffer& b); + + void* data_; + std::size_t size_; + +}; + +namespace detail { + +inline void* buffer_cast_helper(const mutable_buffer& b) +{ + return b.data_; +} + +inline std::size_t buffer_size_helper(const mutable_buffer& b) +{ + return b.size_; +} + +} // namespace detail + +/// Adapts a single modifiable buffer so that it meets the requirements of the +/// MutableBufferSequence concept. +class mutable_buffers_1 + : public mutable_buffer +{ +public: + /// The type for each element in the list of buffers. + typedef mutable_buffer value_type; + + /// A random-access iterator type that may be used to read elements. + typedef const mutable_buffer* const_iterator; + + /// Construct to represent a given memory range. + mutable_buffers_1(void* data, std::size_t size) + : mutable_buffer(data, size) + { + } + + /// Construct to represent a single modifiable buffer. + explicit mutable_buffers_1(const mutable_buffer& b) + : mutable_buffer(b) + { + } + + /// Get a random-access iterator to the first element. + const_iterator begin() const + { + return this; + } + + /// Get a random-access iterator for one past the last element. + const_iterator end() const + { + return begin() + 1; + } +}; + +/// Holds a buffer that cannot be modified. +/** + * The const_buffer class provides a safe representation of a buffer that cannot + * be modified. It does not own the underlying data, and so is cheap to copy or + * assign. + * + * @par Accessing Buffer Contents + * + * The contents of a buffer may be accessed using the @ref buffer_size + * and @ref buffer_cast functions: + * + * @code asio::const_buffer b1 = ...; + * std::size_t s1 = asio::buffer_size(b1); + * const unsigned char* p1 = asio::buffer_cast<const unsigned char*>(b1); + * @endcode + * + * The asio::buffer_cast function permits violations of type safety, so + * uses of it in application code should be carefully considered. + */ +class const_buffer +{ +public: + /// Construct an empty buffer. + const_buffer() + : data_(0), + size_(0) + { + } + + /// Construct a buffer to represent a given memory range. + const_buffer(const void* data, std::size_t size) + : data_(data), + size_(size) + { + } + + /// Construct a non-modifiable buffer from a modifiable one. + const_buffer(const mutable_buffer& b) + : data_(asio::detail::buffer_cast_helper(b)), + size_(asio::detail::buffer_size_helper(b)) + { + } + + +private: + friend const void* asio::detail::buffer_cast_helper( + const const_buffer& b); + friend std::size_t asio::detail::buffer_size_helper( + const const_buffer& b); + + const void* data_; + std::size_t size_; + +}; + +namespace detail { + +inline const void* buffer_cast_helper(const const_buffer& b) +{ + return b.data_; +} + +inline std::size_t buffer_size_helper(const const_buffer& b) +{ + return b.size_; +} + +} // namespace detail + +/// Adapts a single non-modifiable buffer so that it meets the requirements of +/// the ConstBufferSequence concept. +class const_buffers_1 + : public const_buffer +{ +public: + /// The type for each element in the list of buffers. + typedef const_buffer value_type; + + /// A random-access iterator type that may be used to read elements. + typedef const const_buffer* const_iterator; + + /// Construct to represent a given memory range. + const_buffers_1(const void* data, std::size_t size) + : const_buffer(data, size) + { + } + + /// Construct to represent a single non-modifiable buffer. + explicit const_buffers_1(const const_buffer& b) + : const_buffer(b) + { + } + + /// Get a random-access iterator to the first element. + const_iterator begin() const + { + return this; + } + + /// Get a random-access iterator for one past the last element. + const_iterator end() const + { + return begin() + 1; + } +}; + +/// An implementation of both the ConstBufferSequence and MutableBufferSequence +/// concepts to represent a null buffer sequence. +class null_buffers +{ +public: + /// The type for each element in the list of buffers. + typedef mutable_buffer value_type; + + /// A random-access iterator type that may be used to read elements. + typedef const mutable_buffer* const_iterator; + + /// Get a random-access iterator to the first element. + const_iterator begin() const + { + return &buf_; + } + + /// Get a random-access iterator for one past the last element. + const_iterator end() const + { + return &buf_; + } + +private: + mutable_buffer buf_; +}; + +/** @defgroup buffer_size asio::buffer_size + * + * @brief The asio::buffer_size function determines the total number of + * bytes in a buffer or buffer sequence. + */ +/*@{*/ + +/// Get the number of bytes in a modifiable buffer. +inline std::size_t buffer_size(const mutable_buffer& b) +{ + return detail::buffer_size_helper(b); +} + +/// Get the number of bytes in a modifiable buffer. +inline std::size_t buffer_size(const mutable_buffers_1& b) +{ + return detail::buffer_size_helper(b); +} + +/// Get the number of bytes in a non-modifiable buffer. +inline std::size_t buffer_size(const const_buffer& b) +{ + return detail::buffer_size_helper(b); +} + +/// Get the number of bytes in a non-modifiable buffer. +inline std::size_t buffer_size(const const_buffers_1& b) +{ + return detail::buffer_size_helper(b); +} + +/// Get the total number of bytes in a buffer sequence. +/** + * The @c BufferSequence template parameter may meet either of the @c + * ConstBufferSequence or @c MutableBufferSequence type requirements. + */ +template <typename BufferSequence> +inline std::size_t buffer_size(const BufferSequence& b) +{ + std::size_t total_buffer_size = 0; + + typename BufferSequence::const_iterator iter = b.begin(); + typename BufferSequence::const_iterator end = b.end(); + for (; iter != end; ++iter) + total_buffer_size += detail::buffer_size_helper(*iter); + + return total_buffer_size; +} + +/*@}*/ + +/** @defgroup buffer_cast asio::buffer_cast + * + * @brief The asio::buffer_cast function is used to obtain a pointer to + * the underlying memory region associated with a buffer. + * + * @par Examples: + * + * To access the memory of a non-modifiable buffer, use: + * @code asio::const_buffer b1 = ...; + * const unsigned char* p1 = asio::buffer_cast<const unsigned char*>(b1); + * @endcode + * + * To access the memory of a modifiable buffer, use: + * @code asio::mutable_buffer b2 = ...; + * unsigned char* p2 = asio::buffer_cast<unsigned char*>(b2); + * @endcode + * + * The asio::buffer_cast function permits violations of type safety, so + * uses of it in application code should be carefully considered. + */ +/*@{*/ + +/// Cast a non-modifiable buffer to a specified pointer to POD type. +template <typename PointerToPodType> +inline PointerToPodType buffer_cast(const mutable_buffer& b) +{ + return static_cast<PointerToPodType>(detail::buffer_cast_helper(b)); +} + +/// Cast a non-modifiable buffer to a specified pointer to POD type. +template <typename PointerToPodType> +inline PointerToPodType buffer_cast(const const_buffer& b) +{ + return static_cast<PointerToPodType>(detail::buffer_cast_helper(b)); +} + +/*@}*/ + +/// Create a new modifiable buffer that is offset from the start of another. +/** + * @relates mutable_buffer + */ +inline mutable_buffer operator+(const mutable_buffer& b, std::size_t start) +{ + if (start > buffer_size(b)) + return mutable_buffer(); + char* new_data = buffer_cast<char*>(b) + start; + std::size_t new_size = buffer_size(b) - start; + return mutable_buffer(new_data, new_size + ); +} + +/// Create a new modifiable buffer that is offset from the start of another. +/** + * @relates mutable_buffer + */ +inline mutable_buffer operator+(std::size_t start, const mutable_buffer& b) +{ + if (start > buffer_size(b)) + return mutable_buffer(); + char* new_data = buffer_cast<char*>(b) + start; + std::size_t new_size = buffer_size(b) - start; + return mutable_buffer(new_data, new_size + ); +} + +/// Create a new non-modifiable buffer that is offset from the start of another. +/** + * @relates const_buffer + */ +inline const_buffer operator+(const const_buffer& b, std::size_t start) +{ + if (start > buffer_size(b)) + return const_buffer(); + const char* new_data = buffer_cast<const char*>(b) + start; + std::size_t new_size = buffer_size(b) - start; + return const_buffer(new_data, new_size + ); +} + +/// Create a new non-modifiable buffer that is offset from the start of another. +/** + * @relates const_buffer + */ +inline const_buffer operator+(std::size_t start, const const_buffer& b) +{ + if (start > buffer_size(b)) + return const_buffer(); + const char* new_data = buffer_cast<const char*>(b) + start; + std::size_t new_size = buffer_size(b) - start; + return const_buffer(new_data, new_size + ); +} + + +/** @defgroup buffer asio::buffer + * + * @brief The asio::buffer function is used to create a buffer object to + * represent raw memory, an array of POD elements, a vector of POD elements, + * or a std::string. + * + * A buffer object represents a contiguous region of memory as a 2-tuple + * consisting of a pointer and size in bytes. A tuple of the form <tt>{void*, + * size_t}</tt> specifies a mutable (modifiable) region of memory. Similarly, a + * tuple of the form <tt>{const void*, size_t}</tt> specifies a const + * (non-modifiable) region of memory. These two forms correspond to the classes + * mutable_buffer and const_buffer, respectively. To mirror C++'s conversion + * rules, a mutable_buffer is implicitly convertible to a const_buffer, and the + * opposite conversion is not permitted. + * + * The simplest use case involves reading or writing a single buffer of a + * specified size: + * + * @code sock.send(asio::buffer(data, size)); @endcode + * + * In the above example, the return value of asio::buffer meets the + * requirements of the ConstBufferSequence concept so that it may be directly + * passed to the socket's write function. A buffer created for modifiable + * memory also meets the requirements of the MutableBufferSequence concept. + * + * An individual buffer may be created from a builtin array, std::vector, + * std::array or boost::array of POD elements. This helps prevent buffer + * overruns by automatically determining the size of the buffer: + * + * @code char d1[128]; + * size_t bytes_transferred = sock.receive(asio::buffer(d1)); + * + * std::vector<char> d2(128); + * bytes_transferred = sock.receive(asio::buffer(d2)); + * + * std::array<char, 128> d3; + * bytes_transferred = sock.receive(asio::buffer(d3)); + * + * boost::array<char, 128> d4; + * bytes_transferred = sock.receive(asio::buffer(d4)); @endcode + * + * In all three cases above, the buffers created are exactly 128 bytes long. + * Note that a vector is @e never automatically resized when creating or using + * a buffer. The buffer size is determined using the vector's <tt>size()</tt> + * member function, and not its capacity. + * + * @par Accessing Buffer Contents + * + * The contents of a buffer may be accessed using the @ref buffer_size and + * @ref buffer_cast functions: + * + * @code asio::mutable_buffer b1 = ...; + * std::size_t s1 = asio::buffer_size(b1); + * unsigned char* p1 = asio::buffer_cast<unsigned char*>(b1); + * + * asio::const_buffer b2 = ...; + * std::size_t s2 = asio::buffer_size(b2); + * const void* p2 = asio::buffer_cast<const void*>(b2); @endcode + * + * The asio::buffer_cast function permits violations of type safety, so + * uses of it in application code should be carefully considered. + * + * For convenience, the @ref buffer_size function also works on buffer + * sequences (that is, types meeting the ConstBufferSequence or + * MutableBufferSequence type requirements). In this case, the function returns + * the total size of all buffers in the sequence. + * + * @par Buffer Copying + * + * The @ref buffer_copy function may be used to copy raw bytes between + * individual buffers and buffer sequences. + * + * In particular, when used with the @ref buffer_size, the @ref buffer_copy + * function can be used to linearise a sequence of buffers. For example: + * + * @code vector<const_buffer> buffers = ...; + * + * vector<unsigned char> data(asio::buffer_size(buffers)); + * asio::buffer_copy(asio::buffer(data), buffers); @endcode + * + * Note that @ref buffer_copy is implemented in terms of @c memcpy, and + * consequently it cannot be used to copy between overlapping memory regions. + * + * @par Buffer Invalidation + * + * A buffer object does not have any ownership of the memory it refers to. It + * is the responsibility of the application to ensure the memory region remains + * valid until it is no longer required for an I/O operation. When the memory + * is no longer available, the buffer is said to have been invalidated. + * + * For the asio::buffer overloads that accept an argument of type + * std::vector, the buffer objects returned are invalidated by any vector + * operation that also invalidates all references, pointers and iterators + * referring to the elements in the sequence (C++ Std, 23.2.4) + * + * For the asio::buffer overloads that accept an argument of type + * std::basic_string, the buffer objects returned are invalidated according to + * the rules defined for invalidation of references, pointers and iterators + * referring to elements of the sequence (C++ Std, 21.3). + * + * @par Buffer Arithmetic + * + * Buffer objects may be manipulated using simple arithmetic in a safe way + * which helps prevent buffer overruns. Consider an array initialised as + * follows: + * + * @code boost::array<char, 6> a = { 'a', 'b', 'c', 'd', 'e' }; @endcode + * + * A buffer object @c b1 created using: + * + * @code b1 = asio::buffer(a); @endcode + * + * represents the entire array, <tt>{ 'a', 'b', 'c', 'd', 'e' }</tt>. An + * optional second argument to the asio::buffer function may be used to + * limit the size, in bytes, of the buffer: + * + * @code b2 = asio::buffer(a, 3); @endcode + * + * such that @c b2 represents the data <tt>{ 'a', 'b', 'c' }</tt>. Even if the + * size argument exceeds the actual size of the array, the size of the buffer + * object created will be limited to the array size. + * + * An offset may be applied to an existing buffer to create a new one: + * + * @code b3 = b1 + 2; @endcode + * + * where @c b3 will set to represent <tt>{ 'c', 'd', 'e' }</tt>. If the offset + * exceeds the size of the existing buffer, the newly created buffer will be + * empty. + * + * Both an offset and size may be specified to create a buffer that corresponds + * to a specific range of bytes within an existing buffer: + * + * @code b4 = asio::buffer(b1 + 1, 3); @endcode + * + * so that @c b4 will refer to the bytes <tt>{ 'b', 'c', 'd' }</tt>. + * + * @par Buffers and Scatter-Gather I/O + * + * To read or write using multiple buffers (i.e. scatter-gather I/O), multiple + * buffer objects may be assigned into a container that supports the + * MutableBufferSequence (for read) or ConstBufferSequence (for write) concepts: + * + * @code + * char d1[128]; + * std::vector<char> d2(128); + * boost::array<char, 128> d3; + * + * boost::array<mutable_buffer, 3> bufs1 = { + * asio::buffer(d1), + * asio::buffer(d2), + * asio::buffer(d3) }; + * bytes_transferred = sock.receive(bufs1); + * + * std::vector<const_buffer> bufs2; + * bufs2.push_back(asio::buffer(d1)); + * bufs2.push_back(asio::buffer(d2)); + * bufs2.push_back(asio::buffer(d3)); + * bytes_transferred = sock.send(bufs2); @endcode + */ +/*@{*/ + +/// Create a new modifiable buffer from an existing buffer. +/** + * @returns <tt>mutable_buffers_1(b)</tt>. + */ +inline mutable_buffers_1 buffer(const mutable_buffer& b) +{ + return mutable_buffers_1(b); +} + +/// Create a new modifiable buffer from an existing buffer. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * buffer_cast<void*>(b), + * min(buffer_size(b), max_size_in_bytes)); @endcode + */ +inline mutable_buffers_1 buffer(const mutable_buffer& b, + std::size_t max_size_in_bytes) +{ + return mutable_buffers_1( + mutable_buffer(buffer_cast<void*>(b), + buffer_size(b) < max_size_in_bytes + ? buffer_size(b) : max_size_in_bytes + )); +} + +/// Create a new non-modifiable buffer from an existing buffer. +/** + * @returns <tt>const_buffers_1(b)</tt>. + */ +inline const_buffers_1 buffer(const const_buffer& b) +{ + return const_buffers_1(b); +} + +/// Create a new non-modifiable buffer from an existing buffer. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * buffer_cast<const void*>(b), + * min(buffer_size(b), max_size_in_bytes)); @endcode + */ +inline const_buffers_1 buffer(const const_buffer& b, + std::size_t max_size_in_bytes) +{ + return const_buffers_1( + const_buffer(buffer_cast<const void*>(b), + buffer_size(b) < max_size_in_bytes + ? buffer_size(b) : max_size_in_bytes + )); +} + +/// Create a new modifiable buffer that represents the given memory range. +/** + * @returns <tt>mutable_buffers_1(data, size_in_bytes)</tt>. + */ +inline mutable_buffers_1 buffer(void* data, std::size_t size_in_bytes) +{ + return mutable_buffers_1(mutable_buffer(data, size_in_bytes)); +} + +/// Create a new non-modifiable buffer that represents the given memory range. +/** + * @returns <tt>const_buffers_1(data, size_in_bytes)</tt>. + */ +inline const_buffers_1 buffer(const void* data, + std::size_t size_in_bytes) +{ + return const_buffers_1(const_buffer(data, size_in_bytes)); +} + +/// Create a new modifiable buffer that represents the given POD array. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * static_cast<void*>(data), + * N * sizeof(PodType)); @endcode + */ +template <typename PodType, std::size_t N> +inline mutable_buffers_1 buffer(PodType (&data)[N]) +{ + return mutable_buffers_1(mutable_buffer(data, N * sizeof(PodType))); +} + +/// Create a new modifiable buffer that represents the given POD array. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * static_cast<void*>(data), + * min(N * sizeof(PodType), max_size_in_bytes)); @endcode + */ +template <typename PodType, std::size_t N> +inline mutable_buffers_1 buffer(PodType (&data)[N], + std::size_t max_size_in_bytes) +{ + return mutable_buffers_1( + mutable_buffer(data, + N * sizeof(PodType) < max_size_in_bytes + ? N * sizeof(PodType) : max_size_in_bytes)); +} + +/// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * static_cast<const void*>(data), + * N * sizeof(PodType)); @endcode + */ +template <typename PodType, std::size_t N> +inline const_buffers_1 buffer(const PodType (&data)[N]) +{ + return const_buffers_1(const_buffer(data, N * sizeof(PodType))); +} + +/// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * static_cast<const void*>(data), + * min(N * sizeof(PodType), max_size_in_bytes)); @endcode + */ +template <typename PodType, std::size_t N> +inline const_buffers_1 buffer(const PodType (&data)[N], + std::size_t max_size_in_bytes) +{ + return const_buffers_1( + const_buffer(data, + N * sizeof(PodType) < max_size_in_bytes + ? N * sizeof(PodType) : max_size_in_bytes)); +} + +#if defined(ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND) + +// Borland C++ and Sun Studio think the overloads: +// +// unspecified buffer(boost::array<PodType, N>& array ...); +// +// and +// +// unspecified buffer(boost::array<const PodType, N>& array ...); +// +// are ambiguous. This will be worked around by using a buffer_types traits +// class that contains typedefs for the appropriate buffer and container +// classes, based on whether PodType is const or non-const. + +namespace detail { + +template <bool IsConst> +struct buffer_types_base; + +template <> +struct buffer_types_base<false> +{ + typedef mutable_buffer buffer_type; + typedef mutable_buffers_1 container_type; +}; + +template <> +struct buffer_types_base<true> +{ + typedef const_buffer buffer_type; + typedef const_buffers_1 container_type; +}; + +template <typename PodType> +struct buffer_types + : public buffer_types_base<is_const<PodType>::value> +{ +}; + +} // namespace detail + +template <typename PodType, std::size_t N> +inline typename detail::buffer_types<PodType>::container_type +buffer(boost::array<PodType, N>& data) +{ + typedef typename asio::detail::buffer_types<PodType>::buffer_type + buffer_type; + typedef typename asio::detail::buffer_types<PodType>::container_type + container_type; + return container_type( + buffer_type(data.c_array(), data.size() * sizeof(PodType))); +} + +template <typename PodType, std::size_t N> +inline typename detail::buffer_types<PodType>::container_type +buffer(boost::array<PodType, N>& data, std::size_t max_size_in_bytes) +{ + typedef typename asio::detail::buffer_types<PodType>::buffer_type + buffer_type; + typedef typename asio::detail::buffer_types<PodType>::container_type + container_type; + return container_type( + buffer_type(data.c_array(), + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes)); +} + +#else // defined(ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND) + +/// Create a new modifiable buffer that represents the given POD array. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * data.data(), + * data.size() * sizeof(PodType)); @endcode + */ +template <typename PodType, std::size_t N> +inline mutable_buffers_1 buffer(boost::array<PodType, N>& data) +{ + return mutable_buffers_1( + mutable_buffer(data.c_array(), data.size() * sizeof(PodType))); +} + +/// Create a new modifiable buffer that represents the given POD array. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * data.data(), + * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode + */ +template <typename PodType, std::size_t N> +inline mutable_buffers_1 buffer(boost::array<PodType, N>& data, + std::size_t max_size_in_bytes) +{ + return mutable_buffers_1( + mutable_buffer(data.c_array(), + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes)); +} + +/// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * data.size() * sizeof(PodType)); @endcode + */ +template <typename PodType, std::size_t N> +inline const_buffers_1 buffer(boost::array<const PodType, N>& data) +{ + return const_buffers_1( + const_buffer(data.data(), data.size() * sizeof(PodType))); +} + +/// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode + */ +template <typename PodType, std::size_t N> +inline const_buffers_1 buffer(boost::array<const PodType, N>& data, + std::size_t max_size_in_bytes) +{ + return const_buffers_1( + const_buffer(data.data(), + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes)); +} + +#endif // defined(ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND) + +/// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * data.size() * sizeof(PodType)); @endcode + */ +template <typename PodType, std::size_t N> +inline const_buffers_1 buffer(const boost::array<PodType, N>& data) +{ + return const_buffers_1( + const_buffer(data.data(), data.size() * sizeof(PodType))); +} + +/// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode + */ +template <typename PodType, std::size_t N> +inline const_buffers_1 buffer(const boost::array<PodType, N>& data, + std::size_t max_size_in_bytes) +{ + return const_buffers_1( + const_buffer(data.data(), + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes)); +} + + +/// Create a new modifiable buffer that represents the given POD array. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * data.data(), + * data.size() * sizeof(PodType)); @endcode + */ +template <typename PodType, std::size_t N> +inline mutable_buffers_1 buffer(std::array<PodType, N>& data) +{ + return mutable_buffers_1( + mutable_buffer(data.data(), data.size() * sizeof(PodType))); +} + +/// Create a new modifiable buffer that represents the given POD array. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * data.data(), + * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode + */ +template <typename PodType, std::size_t N> +inline mutable_buffers_1 buffer(std::array<PodType, N>& data, + std::size_t max_size_in_bytes) +{ + return mutable_buffers_1( + mutable_buffer(data.data(), + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes)); +} + +/// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * data.size() * sizeof(PodType)); @endcode + */ +template <typename PodType, std::size_t N> +inline const_buffers_1 buffer(std::array<const PodType, N>& data) +{ + return const_buffers_1( + const_buffer(data.data(), data.size() * sizeof(PodType))); +} + +/// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode + */ +template <typename PodType, std::size_t N> +inline const_buffers_1 buffer(std::array<const PodType, N>& data, + std::size_t max_size_in_bytes) +{ + return const_buffers_1( + const_buffer(data.data(), + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes)); +} + +/// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * data.size() * sizeof(PodType)); @endcode + */ +template <typename PodType, std::size_t N> +inline const_buffers_1 buffer(const std::array<PodType, N>& data) +{ + return const_buffers_1( + const_buffer(data.data(), data.size() * sizeof(PodType))); +} + +/// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode + */ +template <typename PodType, std::size_t N> +inline const_buffers_1 buffer(const std::array<PodType, N>& data, + std::size_t max_size_in_bytes) +{ + return const_buffers_1( + const_buffer(data.data(), + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes)); +} + + +/// Create a new modifiable buffer that represents the given POD vector. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * data.size() ? &data[0] : 0, + * data.size() * sizeof(PodType)); @endcode + * + * @note The buffer is invalidated by any vector operation that would also + * invalidate iterators. + */ +template <typename PodType, typename Allocator> +inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data) +{ + return mutable_buffers_1( + mutable_buffer(data.size() ? &data[0] : 0, data.size() * sizeof(PodType) + )); +} + +/// Create a new modifiable buffer that represents the given POD vector. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * data.size() ? &data[0] : 0, + * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode + * + * @note The buffer is invalidated by any vector operation that would also + * invalidate iterators. + */ +template <typename PodType, typename Allocator> +inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data, + std::size_t max_size_in_bytes) +{ + return mutable_buffers_1( + mutable_buffer(data.size() ? &data[0] : 0, + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes + )); +} + +/// Create a new non-modifiable buffer that represents the given POD vector. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.size() ? &data[0] : 0, + * data.size() * sizeof(PodType)); @endcode + * + * @note The buffer is invalidated by any vector operation that would also + * invalidate iterators. + */ +template <typename PodType, typename Allocator> +inline const_buffers_1 buffer( + const std::vector<PodType, Allocator>& data) +{ + return const_buffers_1( + const_buffer(data.size() ? &data[0] : 0, data.size() * sizeof(PodType) + )); +} + +/// Create a new non-modifiable buffer that represents the given POD vector. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.size() ? &data[0] : 0, + * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode + * + * @note The buffer is invalidated by any vector operation that would also + * invalidate iterators. + */ +template <typename PodType, typename Allocator> +inline const_buffers_1 buffer( + const std::vector<PodType, Allocator>& data, std::size_t max_size_in_bytes) +{ + return const_buffers_1( + const_buffer(data.size() ? &data[0] : 0, + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes + )); +} + +/// Create a new non-modifiable buffer that represents the given string. +/** + * @returns <tt>const_buffers_1(data.data(), data.size() * sizeof(Elem))</tt>. + * + * @note The buffer is invalidated by any non-const operation called on the + * given string object. + */ +template <typename Elem, typename Traits, typename Allocator> +inline const_buffers_1 buffer( + const std::basic_string<Elem, Traits, Allocator>& data) +{ + return const_buffers_1(const_buffer(data.data(), data.size() * sizeof(Elem) + )); +} + +/// Create a new non-modifiable buffer that represents the given string. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * min(data.size() * sizeof(Elem), max_size_in_bytes)); @endcode + * + * @note The buffer is invalidated by any non-const operation called on the + * given string object. + */ +template <typename Elem, typename Traits, typename Allocator> +inline const_buffers_1 buffer( + const std::basic_string<Elem, Traits, Allocator>& data, + std::size_t max_size_in_bytes) +{ + return const_buffers_1( + const_buffer(data.data(), + data.size() * sizeof(Elem) < max_size_in_bytes + ? data.size() * sizeof(Elem) : max_size_in_bytes + )); +} + +/*@}*/ + +/** @defgroup buffer_copy asio::buffer_copy + * + * @brief The asio::buffer_copy function is used to copy bytes from a + * source buffer (or buffer sequence) to a target buffer (or buffer sequence). + * + * The @c buffer_copy function is available in two forms: + * + * @li A 2-argument form: @c buffer_copy(target, source) + * + * @li A 3-argument form: @c buffer_copy(target, source, max_bytes_to_copy) + + * Both forms return the number of bytes actually copied. The number of bytes + * copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c If specified, @c max_bytes_to_copy. + * + * This prevents buffer overflow, regardless of the buffer sizes used in the + * copy operation. + * + * Note that @ref buffer_copy is implemented in terms of @c memcpy, and + * consequently it cannot be used to copy between overlapping memory regions. + */ +/*@{*/ + +/// Copies bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A non-modifiable buffer representing the memory region from + * which the bytes will be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffer& target, + const const_buffer& source) +{ + using namespace std; // For memcpy. + std::size_t target_size = buffer_size(target); + std::size_t source_size = buffer_size(source); + std::size_t n = target_size < source_size ? target_size : source_size; + memcpy(buffer_cast<void*>(target), buffer_cast<const void*>(source), n); + return n; +} + +/// Copies bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A non-modifiable buffer representing the memory region from + * which the bytes will be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffer& target, + const const_buffers_1& source) +{ + return buffer_copy(target, static_cast<const const_buffer&>(source)); +} + +/// Copies bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A modifiable buffer representing the memory region from which + * the bytes will be copied. The contents of the source buffer will not be + * modified. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffer& target, + const mutable_buffer& source) +{ + return buffer_copy(target, const_buffer(source)); +} + +/// Copies bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A modifiable buffer representing the memory region from which + * the bytes will be copied. The contents of the source buffer will not be + * modified. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffer& target, + const mutable_buffers_1& source) +{ + return buffer_copy(target, const_buffer(source)); +} + +/// Copies bytes from a source buffer sequence to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A non-modifiable buffer sequence representing the memory + * regions from which the bytes will be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename ConstBufferSequence> +std::size_t buffer_copy(const mutable_buffer& target, + const ConstBufferSequence& source) +{ + std::size_t total_bytes_copied = 0; + + typename ConstBufferSequence::const_iterator source_iter = source.begin(); + typename ConstBufferSequence::const_iterator source_end = source.end(); + + for (mutable_buffer target_buffer(target); + buffer_size(target_buffer) && source_iter != source_end; ++source_iter) + { + const_buffer source_buffer(*source_iter); + std::size_t bytes_copied = buffer_copy(target_buffer, source_buffer); + total_bytes_copied += bytes_copied; + target_buffer = target_buffer + bytes_copied; + } + + return total_bytes_copied; +} + +/// Copies bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A non-modifiable buffer representing the memory region from + * which the bytes will be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffers_1& target, + const const_buffer& source) +{ + return buffer_copy(static_cast<const mutable_buffer&>(target), source); +} + +/// Copies bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A non-modifiable buffer representing the memory region from + * which the bytes will be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffers_1& target, + const const_buffers_1& source) +{ + return buffer_copy(static_cast<const mutable_buffer&>(target), + static_cast<const const_buffer&>(source)); +} + +/// Copies bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A modifiable buffer representing the memory region from which + * the bytes will be copied. The contents of the source buffer will not be + * modified. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffers_1& target, + const mutable_buffer& source) +{ + return buffer_copy(static_cast<const mutable_buffer&>(target), + const_buffer(source)); +} + +/// Copies bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A modifiable buffer representing the memory region from which + * the bytes will be copied. The contents of the source buffer will not be + * modified. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffers_1& target, + const mutable_buffers_1& source) +{ + return buffer_copy(static_cast<const mutable_buffer&>(target), + const_buffer(source)); +} + +/// Copies bytes from a source buffer sequence to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A non-modifiable buffer sequence representing the memory + * regions from which the bytes will be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename ConstBufferSequence> +inline std::size_t buffer_copy(const mutable_buffers_1& target, + const ConstBufferSequence& source) +{ + return buffer_copy(static_cast<const mutable_buffer&>(target), source); +} + +/// Copies bytes from a source buffer to a target buffer sequence. +/** + * @param target A modifiable buffer sequence representing the memory regions to + * which the bytes will be copied. + * + * @param source A non-modifiable buffer representing the memory region from + * which the bytes will be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename MutableBufferSequence> +std::size_t buffer_copy(const MutableBufferSequence& target, + const const_buffer& source) +{ + std::size_t total_bytes_copied = 0; + + typename MutableBufferSequence::const_iterator target_iter = target.begin(); + typename MutableBufferSequence::const_iterator target_end = target.end(); + + for (const_buffer source_buffer(source); + buffer_size(source_buffer) && target_iter != target_end; ++target_iter) + { + mutable_buffer target_buffer(*target_iter); + std::size_t bytes_copied = buffer_copy(target_buffer, source_buffer); + total_bytes_copied += bytes_copied; + source_buffer = source_buffer + bytes_copied; + } + + return total_bytes_copied; +} + +/// Copies bytes from a source buffer to a target buffer sequence. +/** + * @param target A modifiable buffer sequence representing the memory regions to + * which the bytes will be copied. + * + * @param source A non-modifiable buffer representing the memory region from + * which the bytes will be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename MutableBufferSequence> +inline std::size_t buffer_copy(const MutableBufferSequence& target, + const const_buffers_1& source) +{ + return buffer_copy(target, static_cast<const const_buffer&>(source)); +} + +/// Copies bytes from a source buffer to a target buffer sequence. +/** + * @param target A modifiable buffer sequence representing the memory regions to + * which the bytes will be copied. + * + * @param source A modifiable buffer representing the memory region from which + * the bytes will be copied. The contents of the source buffer will not be + * modified. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename MutableBufferSequence> +inline std::size_t buffer_copy(const MutableBufferSequence& target, + const mutable_buffer& source) +{ + return buffer_copy(target, const_buffer(source)); +} + +/// Copies bytes from a source buffer to a target buffer sequence. +/** + * @param target A modifiable buffer sequence representing the memory regions to + * which the bytes will be copied. + * + * @param source A modifiable buffer representing the memory region from which + * the bytes will be copied. The contents of the source buffer will not be + * modified. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename MutableBufferSequence> +inline std::size_t buffer_copy(const MutableBufferSequence& target, + const mutable_buffers_1& source) +{ + return buffer_copy(target, const_buffer(source)); +} + +/// Copies bytes from a source buffer sequence to a target buffer sequence. +/** + * @param target A modifiable buffer sequence representing the memory regions to + * which the bytes will be copied. + * + * @param source A non-modifiable buffer sequence representing the memory + * regions from which the bytes will be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename MutableBufferSequence, typename ConstBufferSequence> +std::size_t buffer_copy(const MutableBufferSequence& target, + const ConstBufferSequence& source) +{ + std::size_t total_bytes_copied = 0; + + typename MutableBufferSequence::const_iterator target_iter = target.begin(); + typename MutableBufferSequence::const_iterator target_end = target.end(); + std::size_t target_buffer_offset = 0; + + typename ConstBufferSequence::const_iterator source_iter = source.begin(); + typename ConstBufferSequence::const_iterator source_end = source.end(); + std::size_t source_buffer_offset = 0; + + while (target_iter != target_end && source_iter != source_end) + { + mutable_buffer target_buffer = + mutable_buffer(*target_iter) + target_buffer_offset; + + const_buffer source_buffer = + const_buffer(*source_iter) + source_buffer_offset; + + std::size_t bytes_copied = buffer_copy(target_buffer, source_buffer); + total_bytes_copied += bytes_copied; + + if (bytes_copied == buffer_size(target_buffer)) + { + ++target_iter; + target_buffer_offset = 0; + } + else + target_buffer_offset += bytes_copied; + + if (bytes_copied == buffer_size(source_buffer)) + { + ++source_iter; + source_buffer_offset = 0; + } + else + source_buffer_offset += bytes_copied; + } + + return total_bytes_copied; +} + +/// Copies a limited number of bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A non-modifiable buffer representing the memory region from + * which the bytes will be copied. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffer& target, + const const_buffer& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(buffer(target, max_bytes_to_copy), source); +} + +/// Copies a limited number of bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A non-modifiable buffer representing the memory region from + * which the bytes will be copied. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffer& target, + const const_buffers_1& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(buffer(target, max_bytes_to_copy), source); +} + +/// Copies a limited number of bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A modifiable buffer representing the memory region from which + * the bytes will be copied. The contents of the source buffer will not be + * modified. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffer& target, + const mutable_buffer& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(buffer(target, max_bytes_to_copy), source); +} + +/// Copies a limited number of bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A modifiable buffer representing the memory region from which + * the bytes will be copied. The contents of the source buffer will not be + * modified. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffer& target, + const mutable_buffers_1& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(buffer(target, max_bytes_to_copy), source); +} + +/// Copies a limited number of bytes from a source buffer sequence to a target +/// buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A non-modifiable buffer sequence representing the memory + * regions from which the bytes will be copied. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename ConstBufferSequence> +inline std::size_t buffer_copy(const mutable_buffer& target, + const ConstBufferSequence& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(buffer(target, max_bytes_to_copy), source); +} + +/// Copies a limited number of bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A non-modifiable buffer representing the memory region from + * which the bytes will be copied. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffers_1& target, + const const_buffer& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(buffer(target, max_bytes_to_copy), source); +} + +/// Copies a limited number of bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A non-modifiable buffer representing the memory region from + * which the bytes will be copied. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffers_1& target, + const const_buffers_1& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(buffer(target, max_bytes_to_copy), source); +} + +/// Copies a limited number of bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A modifiable buffer representing the memory region from which + * the bytes will be copied. The contents of the source buffer will not be + * modified. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffers_1& target, + const mutable_buffer& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(buffer(target, max_bytes_to_copy), source); +} + +/// Copies a limited number of bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A modifiable buffer representing the memory region from which + * the bytes will be copied. The contents of the source buffer will not be + * modified. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffers_1& target, + const mutable_buffers_1& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(buffer(target, max_bytes_to_copy), source); +} + +/// Copies a limited number of bytes from a source buffer sequence to a target +/// buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A non-modifiable buffer sequence representing the memory + * regions from which the bytes will be copied. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename ConstBufferSequence> +inline std::size_t buffer_copy(const mutable_buffers_1& target, + const ConstBufferSequence& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(buffer(target, max_bytes_to_copy), source); +} + +/// Copies a limited number of bytes from a source buffer to a target buffer +/// sequence. +/** + * @param target A modifiable buffer sequence representing the memory regions to + * which the bytes will be copied. + * + * @param source A non-modifiable buffer representing the memory region from + * which the bytes will be copied. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename MutableBufferSequence> +inline std::size_t buffer_copy(const MutableBufferSequence& target, + const const_buffer& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(target, buffer(source, max_bytes_to_copy)); +} + +/// Copies a limited number of bytes from a source buffer to a target buffer +/// sequence. +/** + * @param target A modifiable buffer sequence representing the memory regions to + * which the bytes will be copied. + * + * @param source A non-modifiable buffer representing the memory region from + * which the bytes will be copied. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename MutableBufferSequence> +inline std::size_t buffer_copy(const MutableBufferSequence& target, + const const_buffers_1& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(target, buffer(source, max_bytes_to_copy)); +} + +/// Copies a limited number of bytes from a source buffer to a target buffer +/// sequence. +/** + * @param target A modifiable buffer sequence representing the memory regions to + * which the bytes will be copied. + * + * @param source A modifiable buffer representing the memory region from which + * the bytes will be copied. The contents of the source buffer will not be + * modified. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename MutableBufferSequence> +inline std::size_t buffer_copy(const MutableBufferSequence& target, + const mutable_buffer& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(target, buffer(source, max_bytes_to_copy)); +} + +/// Copies a limited number of bytes from a source buffer to a target buffer +/// sequence. +/** + * @param target A modifiable buffer sequence representing the memory regions to + * which the bytes will be copied. + * + * @param source A modifiable buffer representing the memory region from which + * the bytes will be copied. The contents of the source buffer will not be + * modified. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename MutableBufferSequence> +inline std::size_t buffer_copy(const MutableBufferSequence& target, + const mutable_buffers_1& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(target, buffer(source, max_bytes_to_copy)); +} + +/// Copies a limited number of bytes from a source buffer sequence to a target +/// buffer sequence. +/** + * @param target A modifiable buffer sequence representing the memory regions to + * which the bytes will be copied. + * + * @param source A non-modifiable buffer sequence representing the memory + * regions from which the bytes will be copied. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename MutableBufferSequence, typename ConstBufferSequence> +std::size_t buffer_copy(const MutableBufferSequence& target, + const ConstBufferSequence& source, std::size_t max_bytes_to_copy) +{ + std::size_t total_bytes_copied = 0; + + typename MutableBufferSequence::const_iterator target_iter = target.begin(); + typename MutableBufferSequence::const_iterator target_end = target.end(); + std::size_t target_buffer_offset = 0; + + typename ConstBufferSequence::const_iterator source_iter = source.begin(); + typename ConstBufferSequence::const_iterator source_end = source.end(); + std::size_t source_buffer_offset = 0; + + while (total_bytes_copied != max_bytes_to_copy + && target_iter != target_end && source_iter != source_end) + { + mutable_buffer target_buffer = + mutable_buffer(*target_iter) + target_buffer_offset; + + const_buffer source_buffer = + const_buffer(*source_iter) + source_buffer_offset; + + std::size_t bytes_copied = buffer_copy(target_buffer, + source_buffer, max_bytes_to_copy - total_bytes_copied); + total_bytes_copied += bytes_copied; + + if (bytes_copied == buffer_size(target_buffer)) + { + ++target_iter; + target_buffer_offset = 0; + } + else + target_buffer_offset += bytes_copied; + + if (bytes_copied == buffer_size(source_buffer)) + { + ++source_iter; + source_buffer_offset = 0; + } + else + source_buffer_offset += bytes_copied; + } + + return total_bytes_copied; +} + +/*@}*/ + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_BUFFER_HPP diff --git a/asio-1.10.6/include/asio/completion_condition.hpp b/asio-1.10.6/include/asio/completion_condition.hpp new file mode 100644 index 0000000..127506b --- /dev/null +++ b/asio-1.10.6/include/asio/completion_condition.hpp @@ -0,0 +1,203 @@ +// +// completion_condition.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_COMPLETION_CONDITION_HPP +#define ASIO_COMPLETION_CONDITION_HPP + + +#include "asio/detail/config.hpp" +#include <cstddef> + +#include "asio/detail/push_options.hpp" + +namespace asio { + +namespace detail { + +// The default maximum number of bytes to transfer in a single operation. +enum default_max_transfer_size_t { default_max_transfer_size = 65536 }; + +// Adapt result of old-style completion conditions (which had a bool result +// where true indicated that the operation was complete). +inline std::size_t adapt_completion_condition_result(bool result) +{ + return result ? 0 : default_max_transfer_size; +} + +// Adapt result of current completion conditions (which have a size_t result +// where 0 means the operation is complete, and otherwise the result is the +// maximum number of bytes to transfer on the next underlying operation). +inline std::size_t adapt_completion_condition_result(std::size_t result) +{ + return result; +} + +class transfer_all_t +{ +public: + typedef std::size_t result_type; + + template <typename Error> + std::size_t operator()(const Error& err, std::size_t) + { + return !!err ? 0 : default_max_transfer_size; + } +}; + +class transfer_at_least_t +{ +public: + typedef std::size_t result_type; + + explicit transfer_at_least_t(std::size_t minimum) + : minimum_(minimum) + { + } + + template <typename Error> + std::size_t operator()(const Error& err, std::size_t bytes_transferred) + { + return (!!err || bytes_transferred >= minimum_) + ? 0 : default_max_transfer_size; + } + +private: + std::size_t minimum_; +}; + +class transfer_exactly_t +{ +public: + typedef std::size_t result_type; + + explicit transfer_exactly_t(std::size_t size) + : size_(size) + { + } + + template <typename Error> + std::size_t operator()(const Error& err, std::size_t bytes_transferred) + { + return (!!err || bytes_transferred >= size_) ? 0 : + (size_ - bytes_transferred < default_max_transfer_size + ? size_ - bytes_transferred : std::size_t(default_max_transfer_size)); + } + +private: + std::size_t size_; +}; + +} // namespace detail + +/** + * @defgroup completion_condition Completion Condition Function Objects + * + * Function objects used for determining when a read or write operation should + * complete. + */ +/*@{*/ + +/// Return a completion condition function object that indicates that a read or +/// write operation should continue until all of the data has been transferred, +/// or until an error occurs. +/** + * This function is used to create an object, of unspecified type, that meets + * CompletionCondition requirements. + * + * @par Example + * Reading until a buffer is full: + * @code + * boost::array<char, 128> buf; + * asio::error_code ec; + * std::size_t n = asio::read( + * sock, asio::buffer(buf), + * asio::transfer_all(), ec); + * if (ec) + * { + * // An error occurred. + * } + * else + * { + * // n == 128 + * } + * @endcode + */ +inline detail::transfer_all_t transfer_all() +{ + return detail::transfer_all_t(); +} + +/// Return a completion condition function object that indicates that a read or +/// write operation should continue until a minimum number of bytes has been +/// transferred, or until an error occurs. +/** + * This function is used to create an object, of unspecified type, that meets + * CompletionCondition requirements. + * + * @par Example + * Reading until a buffer is full or contains at least 64 bytes: + * @code + * boost::array<char, 128> buf; + * asio::error_code ec; + * std::size_t n = asio::read( + * sock, asio::buffer(buf), + * asio::transfer_at_least(64), ec); + * if (ec) + * { + * // An error occurred. + * } + * else + * { + * // n >= 64 && n <= 128 + * } + * @endcode + */ +inline detail::transfer_at_least_t transfer_at_least(std::size_t minimum) +{ + return detail::transfer_at_least_t(minimum); +} + +/// Return a completion condition function object that indicates that a read or +/// write operation should continue until an exact number of bytes has been +/// transferred, or until an error occurs. +/** + * This function is used to create an object, of unspecified type, that meets + * CompletionCondition requirements. + * + * @par Example + * Reading until a buffer is full or contains exactly 64 bytes: + * @code + * boost::array<char, 128> buf; + * asio::error_code ec; + * std::size_t n = asio::read( + * sock, asio::buffer(buf), + * asio::transfer_exactly(64), ec); + * if (ec) + * { + * // An error occurred. + * } + * else + * { + * // n == 64 + * } + * @endcode + */ +inline detail::transfer_exactly_t transfer_exactly(std::size_t size) +{ + return detail::transfer_exactly_t(size); +} + +/*@}*/ + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_COMPLETION_CONDITION_HPP diff --git a/asio-1.10.6/include/asio/connect.hpp b/asio-1.10.6/include/asio/connect.hpp new file mode 100644 index 0000000..d0f245c --- /dev/null +++ b/asio-1.10.6/include/asio/connect.hpp @@ -0,0 +1,820 @@ +// +// connect.hpp +// ~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_CONNECT_HPP +#define ASIO_CONNECT_HPP + + +#include "asio/detail/config.hpp" +#include "asio/async_result.hpp" +#include "asio/basic_socket.hpp" +#include "asio/error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +/** + * @defgroup connect asio::connect + * + * @brief Establishes a socket connection by trying each endpoint in a sequence. + */ +/*@{*/ + +/// Establishes a socket connection by trying each endpoint in a sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c connect member + * function, once for each endpoint in the sequence, until a connection is + * successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param begin An iterator pointing to the start of a sequence of endpoints. + * + * @returns On success, an iterator denoting the successfully connected + * endpoint. Otherwise, the end iterator. + * + * @throws asio::system_error Thrown on failure. If the sequence is + * empty, the associated @c error_code is asio::error::not_found. + * Otherwise, contains the error from the last connection attempt. + * + * @note This overload assumes that a default constructed object of type @c + * Iterator represents the end of the sequence. This is a valid assumption for + * iterator types such as @c asio::ip::tcp::resolver::iterator. + * + * @par Example + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::socket s(io_service); + * asio::connect(s, r.resolve(q)); @endcode + */ +template <typename Protocol, typename SocketService, typename Iterator> +Iterator connect(basic_socket<Protocol, SocketService>& s, Iterator begin); + +/// Establishes a socket connection by trying each endpoint in a sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c connect member + * function, once for each endpoint in the sequence, until a connection is + * successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param begin An iterator pointing to the start of a sequence of endpoints. + * + * @param ec Set to indicate what error occurred, if any. If the sequence is + * empty, set to asio::error::not_found. Otherwise, contains the error + * from the last connection attempt. + * + * @returns On success, an iterator denoting the successfully connected + * endpoint. Otherwise, the end iterator. + * + * @note This overload assumes that a default constructed object of type @c + * Iterator represents the end of the sequence. This is a valid assumption for + * iterator types such as @c asio::ip::tcp::resolver::iterator. + * + * @par Example + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::socket s(io_service); + * asio::error_code ec; + * asio::connect(s, r.resolve(q), ec); + * if (ec) + * { + * // An error occurred. + * } @endcode + */ +template <typename Protocol, typename SocketService, typename Iterator> +Iterator connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, asio::error_code& ec); + +/// Establishes a socket connection by trying each endpoint in a sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c connect member + * function, once for each endpoint in the sequence, until a connection is + * successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param begin An iterator pointing to the start of a sequence of endpoints. + * + * @param end An iterator pointing to the end of a sequence of endpoints. + * + * @returns On success, an iterator denoting the successfully connected + * endpoint. Otherwise, the end iterator. + * + * @throws asio::system_error Thrown on failure. If the sequence is + * empty, the associated @c error_code is asio::error::not_found. + * Otherwise, contains the error from the last connection attempt. + * + * @par Example + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::resolver::iterator i = r.resolve(q), end; + * tcp::socket s(io_service); + * asio::connect(s, i, end); @endcode + */ +template <typename Protocol, typename SocketService, typename Iterator> +Iterator connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, Iterator end); + +/// Establishes a socket connection by trying each endpoint in a sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c connect member + * function, once for each endpoint in the sequence, until a connection is + * successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param begin An iterator pointing to the start of a sequence of endpoints. + * + * @param end An iterator pointing to the end of a sequence of endpoints. + * + * @param ec Set to indicate what error occurred, if any. If the sequence is + * empty, set to asio::error::not_found. Otherwise, contains the error + * from the last connection attempt. + * + * @returns On success, an iterator denoting the successfully connected + * endpoint. Otherwise, the end iterator. + * + * @par Example + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::resolver::iterator i = r.resolve(q), end; + * tcp::socket s(io_service); + * asio::error_code ec; + * asio::connect(s, i, end, ec); + * if (ec) + * { + * // An error occurred. + * } @endcode + */ +template <typename Protocol, typename SocketService, typename Iterator> +Iterator connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, Iterator end, asio::error_code& ec); + +/// Establishes a socket connection by trying each endpoint in a sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c connect member + * function, once for each endpoint in the sequence, until a connection is + * successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param begin An iterator pointing to the start of a sequence of endpoints. + * + * @param connect_condition A function object that is called prior to each + * connection attempt. The signature of the function object must be: + * @code Iterator connect_condition( + * const asio::error_code& ec, + * Iterator next); @endcode + * The @c ec parameter contains the result from the most recent connect + * operation. Before the first connection attempt, @c ec is always set to + * indicate success. The @c next parameter is an iterator pointing to the next + * endpoint to be tried. The function object should return the next iterator, + * but is permitted to return a different iterator so that endpoints may be + * skipped. The implementation guarantees that the function object will never + * be called with the end iterator. + * + * @returns On success, an iterator denoting the successfully connected + * endpoint. Otherwise, the end iterator. + * + * @throws asio::system_error Thrown on failure. If the sequence is + * empty, the associated @c error_code is asio::error::not_found. + * Otherwise, contains the error from the last connection attempt. + * + * @note This overload assumes that a default constructed object of type @c + * Iterator represents the end of the sequence. This is a valid assumption for + * iterator types such as @c asio::ip::tcp::resolver::iterator. + * + * @par Example + * The following connect condition function object can be used to output + * information about the individual connection attempts: + * @code struct my_connect_condition + * { + * template <typename Iterator> + * Iterator operator()( + * const asio::error_code& ec, + * Iterator next) + * { + * if (ec) std::cout << "Error: " << ec.message() << std::endl; + * std::cout << "Trying: " << next->endpoint() << std::endl; + * return next; + * } + * }; @endcode + * It would be used with the asio::connect function as follows: + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::socket s(io_service); + * tcp::resolver::iterator i = asio::connect( + * s, r.resolve(q), my_connect_condition()); + * std::cout << "Connected to: " << i->endpoint() << std::endl; @endcode + */ +template <typename Protocol, typename SocketService, + typename Iterator, typename ConnectCondition> +Iterator connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, ConnectCondition connect_condition); + +/// Establishes a socket connection by trying each endpoint in a sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c connect member + * function, once for each endpoint in the sequence, until a connection is + * successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param begin An iterator pointing to the start of a sequence of endpoints. + * + * @param connect_condition A function object that is called prior to each + * connection attempt. The signature of the function object must be: + * @code Iterator connect_condition( + * const asio::error_code& ec, + * Iterator next); @endcode + * The @c ec parameter contains the result from the most recent connect + * operation. Before the first connection attempt, @c ec is always set to + * indicate success. The @c next parameter is an iterator pointing to the next + * endpoint to be tried. The function object should return the next iterator, + * but is permitted to return a different iterator so that endpoints may be + * skipped. The implementation guarantees that the function object will never + * be called with the end iterator. + * + * @param ec Set to indicate what error occurred, if any. If the sequence is + * empty, set to asio::error::not_found. Otherwise, contains the error + * from the last connection attempt. + * + * @returns On success, an iterator denoting the successfully connected + * endpoint. Otherwise, the end iterator. + * + * @note This overload assumes that a default constructed object of type @c + * Iterator represents the end of the sequence. This is a valid assumption for + * iterator types such as @c asio::ip::tcp::resolver::iterator. + * + * @par Example + * The following connect condition function object can be used to output + * information about the individual connection attempts: + * @code struct my_connect_condition + * { + * template <typename Iterator> + * Iterator operator()( + * const asio::error_code& ec, + * Iterator next) + * { + * if (ec) std::cout << "Error: " << ec.message() << std::endl; + * std::cout << "Trying: " << next->endpoint() << std::endl; + * return next; + * } + * }; @endcode + * It would be used with the asio::connect function as follows: + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::socket s(io_service); + * asio::error_code ec; + * tcp::resolver::iterator i = asio::connect( + * s, r.resolve(q), my_connect_condition(), ec); + * if (ec) + * { + * // An error occurred. + * } + * else + * { + * std::cout << "Connected to: " << i->endpoint() << std::endl; + * } @endcode + */ +template <typename Protocol, typename SocketService, + typename Iterator, typename ConnectCondition> +Iterator connect(basic_socket<Protocol, SocketService>& s, Iterator begin, + ConnectCondition connect_condition, asio::error_code& ec); + +/// Establishes a socket connection by trying each endpoint in a sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c connect member + * function, once for each endpoint in the sequence, until a connection is + * successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param begin An iterator pointing to the start of a sequence of endpoints. + * + * @param end An iterator pointing to the end of a sequence of endpoints. + * + * @param connect_condition A function object that is called prior to each + * connection attempt. The signature of the function object must be: + * @code Iterator connect_condition( + * const asio::error_code& ec, + * Iterator next); @endcode + * The @c ec parameter contains the result from the most recent connect + * operation. Before the first connection attempt, @c ec is always set to + * indicate success. The @c next parameter is an iterator pointing to the next + * endpoint to be tried. The function object should return the next iterator, + * but is permitted to return a different iterator so that endpoints may be + * skipped. The implementation guarantees that the function object will never + * be called with the end iterator. + * + * @returns On success, an iterator denoting the successfully connected + * endpoint. Otherwise, the end iterator. + * + * @throws asio::system_error Thrown on failure. If the sequence is + * empty, the associated @c error_code is asio::error::not_found. + * Otherwise, contains the error from the last connection attempt. + * + * @par Example + * The following connect condition function object can be used to output + * information about the individual connection attempts: + * @code struct my_connect_condition + * { + * template <typename Iterator> + * Iterator operator()( + * const asio::error_code& ec, + * Iterator next) + * { + * if (ec) std::cout << "Error: " << ec.message() << std::endl; + * std::cout << "Trying: " << next->endpoint() << std::endl; + * return next; + * } + * }; @endcode + * It would be used with the asio::connect function as follows: + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::resolver::iterator i = r.resolve(q), end; + * tcp::socket s(io_service); + * i = asio::connect(s, i, end, my_connect_condition()); + * std::cout << "Connected to: " << i->endpoint() << std::endl; @endcode + */ +template <typename Protocol, typename SocketService, + typename Iterator, typename ConnectCondition> +Iterator connect(basic_socket<Protocol, SocketService>& s, Iterator begin, + Iterator end, ConnectCondition connect_condition); + +/// Establishes a socket connection by trying each endpoint in a sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c connect member + * function, once for each endpoint in the sequence, until a connection is + * successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param begin An iterator pointing to the start of a sequence of endpoints. + * + * @param end An iterator pointing to the end of a sequence of endpoints. + * + * @param connect_condition A function object that is called prior to each + * connection attempt. The signature of the function object must be: + * @code Iterator connect_condition( + * const asio::error_code& ec, + * Iterator next); @endcode + * The @c ec parameter contains the result from the most recent connect + * operation. Before the first connection attempt, @c ec is always set to + * indicate success. The @c next parameter is an iterator pointing to the next + * endpoint to be tried. The function object should return the next iterator, + * but is permitted to return a different iterator so that endpoints may be + * skipped. The implementation guarantees that the function object will never + * be called with the end iterator. + * + * @param ec Set to indicate what error occurred, if any. If the sequence is + * empty, set to asio::error::not_found. Otherwise, contains the error + * from the last connection attempt. + * + * @returns On success, an iterator denoting the successfully connected + * endpoint. Otherwise, the end iterator. + * + * @par Example + * The following connect condition function object can be used to output + * information about the individual connection attempts: + * @code struct my_connect_condition + * { + * template <typename Iterator> + * Iterator operator()( + * const asio::error_code& ec, + * Iterator next) + * { + * if (ec) std::cout << "Error: " << ec.message() << std::endl; + * std::cout << "Trying: " << next->endpoint() << std::endl; + * return next; + * } + * }; @endcode + * It would be used with the asio::connect function as follows: + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::resolver::iterator i = r.resolve(q), end; + * tcp::socket s(io_service); + * asio::error_code ec; + * i = asio::connect(s, i, end, my_connect_condition(), ec); + * if (ec) + * { + * // An error occurred. + * } + * else + * { + * std::cout << "Connected to: " << i->endpoint() << std::endl; + * } @endcode + */ +template <typename Protocol, typename SocketService, + typename Iterator, typename ConnectCondition> +Iterator connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, Iterator end, ConnectCondition connect_condition, + asio::error_code& ec); + +/*@}*/ + +/** + * @defgroup async_connect asio::async_connect + * + * @brief Asynchronously establishes a socket connection by trying each + * endpoint in a sequence. + */ +/*@{*/ + +/// Asynchronously establishes a socket connection by trying each endpoint in a +/// sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c async_connect + * member function, once for each endpoint in the sequence, until a connection + * is successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param begin An iterator pointing to the start of a sequence of endpoints. + * + * @param handler The handler to be called when the connect operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * // Result of operation. if the sequence is empty, set to + * // asio::error::not_found. Otherwise, contains the + * // error from the last connection attempt. + * const asio::error_code& error, + * + * // On success, an iterator denoting the successfully + * // connected endpoint. Otherwise, the end iterator. + * Iterator iterator + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note This overload assumes that a default constructed object of type @c + * Iterator represents the end of the sequence. This is a valid assumption for + * iterator types such as @c asio::ip::tcp::resolver::iterator. + * + * @par Example + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::socket s(io_service); + * + * // ... + * + * r.async_resolve(q, resolve_handler); + * + * // ... + * + * void resolve_handler( + * const asio::error_code& ec, + * tcp::resolver::iterator i) + * { + * if (!ec) + * { + * asio::async_connect(s, i, connect_handler); + * } + * } + * + * // ... + * + * void connect_handler( + * const asio::error_code& ec, + * tcp::resolver::iterator i) + * { + * // ... + * } @endcode + */ +template <typename Protocol, typename SocketService, + typename Iterator, typename ComposedConnectHandler> +ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler, + void (asio::error_code, Iterator)) +async_connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, ASIO_MOVE_ARG(ComposedConnectHandler) handler); + +/// Asynchronously establishes a socket connection by trying each endpoint in a +/// sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c async_connect + * member function, once for each endpoint in the sequence, until a connection + * is successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param begin An iterator pointing to the start of a sequence of endpoints. + * + * @param end An iterator pointing to the end of a sequence of endpoints. + * + * @param handler The handler to be called when the connect operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * // Result of operation. if the sequence is empty, set to + * // asio::error::not_found. Otherwise, contains the + * // error from the last connection attempt. + * const asio::error_code& error, + * + * // On success, an iterator denoting the successfully + * // connected endpoint. Otherwise, the end iterator. + * Iterator iterator + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @par Example + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::socket s(io_service); + * + * // ... + * + * r.async_resolve(q, resolve_handler); + * + * // ... + * + * void resolve_handler( + * const asio::error_code& ec, + * tcp::resolver::iterator i) + * { + * if (!ec) + * { + * tcp::resolver::iterator end; + * asio::async_connect(s, i, end, connect_handler); + * } + * } + * + * // ... + * + * void connect_handler( + * const asio::error_code& ec, + * tcp::resolver::iterator i) + * { + * // ... + * } @endcode + */ +template <typename Protocol, typename SocketService, + typename Iterator, typename ComposedConnectHandler> +ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler, + void (asio::error_code, Iterator)) +async_connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, Iterator end, + ASIO_MOVE_ARG(ComposedConnectHandler) handler); + +/// Asynchronously establishes a socket connection by trying each endpoint in a +/// sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c async_connect + * member function, once for each endpoint in the sequence, until a connection + * is successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param begin An iterator pointing to the start of a sequence of endpoints. + * + * @param connect_condition A function object that is called prior to each + * connection attempt. The signature of the function object must be: + * @code Iterator connect_condition( + * const asio::error_code& ec, + * Iterator next); @endcode + * The @c ec parameter contains the result from the most recent connect + * operation. Before the first connection attempt, @c ec is always set to + * indicate success. The @c next parameter is an iterator pointing to the next + * endpoint to be tried. The function object should return the next iterator, + * but is permitted to return a different iterator so that endpoints may be + * skipped. The implementation guarantees that the function object will never + * be called with the end iterator. + * + * @param handler The handler to be called when the connect operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * // Result of operation. if the sequence is empty, set to + * // asio::error::not_found. Otherwise, contains the + * // error from the last connection attempt. + * const asio::error_code& error, + * + * // On success, an iterator denoting the successfully + * // connected endpoint. Otherwise, the end iterator. + * Iterator iterator + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note This overload assumes that a default constructed object of type @c + * Iterator represents the end of the sequence. This is a valid assumption for + * iterator types such as @c asio::ip::tcp::resolver::iterator. + * + * @par Example + * The following connect condition function object can be used to output + * information about the individual connection attempts: + * @code struct my_connect_condition + * { + * template <typename Iterator> + * Iterator operator()( + * const asio::error_code& ec, + * Iterator next) + * { + * if (ec) std::cout << "Error: " << ec.message() << std::endl; + * std::cout << "Trying: " << next->endpoint() << std::endl; + * return next; + * } + * }; @endcode + * It would be used with the asio::connect function as follows: + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::socket s(io_service); + * + * // ... + * + * r.async_resolve(q, resolve_handler); + * + * // ... + * + * void resolve_handler( + * const asio::error_code& ec, + * tcp::resolver::iterator i) + * { + * if (!ec) + * { + * asio::async_connect(s, i, + * my_connect_condition(), + * connect_handler); + * } + * } + * + * // ... + * + * void connect_handler( + * const asio::error_code& ec, + * tcp::resolver::iterator i) + * { + * if (ec) + * { + * // An error occurred. + * } + * else + * { + * std::cout << "Connected to: " << i->endpoint() << std::endl; + * } + * } @endcode + */ +template <typename Protocol, typename SocketService, typename Iterator, + typename ConnectCondition, typename ComposedConnectHandler> +ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler, + void (asio::error_code, Iterator)) +async_connect(basic_socket<Protocol, SocketService>& s, Iterator begin, + ConnectCondition connect_condition, + ASIO_MOVE_ARG(ComposedConnectHandler) handler); + +/// Asynchronously establishes a socket connection by trying each endpoint in a +/// sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c async_connect + * member function, once for each endpoint in the sequence, until a connection + * is successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param begin An iterator pointing to the start of a sequence of endpoints. + * + * @param end An iterator pointing to the end of a sequence of endpoints. + * + * @param connect_condition A function object that is called prior to each + * connection attempt. The signature of the function object must be: + * @code Iterator connect_condition( + * const asio::error_code& ec, + * Iterator next); @endcode + * The @c ec parameter contains the result from the most recent connect + * operation. Before the first connection attempt, @c ec is always set to + * indicate success. The @c next parameter is an iterator pointing to the next + * endpoint to be tried. The function object should return the next iterator, + * but is permitted to return a different iterator so that endpoints may be + * skipped. The implementation guarantees that the function object will never + * be called with the end iterator. + * + * @param handler The handler to be called when the connect operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * // Result of operation. if the sequence is empty, set to + * // asio::error::not_found. Otherwise, contains the + * // error from the last connection attempt. + * const asio::error_code& error, + * + * // On success, an iterator denoting the successfully + * // connected endpoint. Otherwise, the end iterator. + * Iterator iterator + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @par Example + * The following connect condition function object can be used to output + * information about the individual connection attempts: + * @code struct my_connect_condition + * { + * template <typename Iterator> + * Iterator operator()( + * const asio::error_code& ec, + * Iterator next) + * { + * if (ec) std::cout << "Error: " << ec.message() << std::endl; + * std::cout << "Trying: " << next->endpoint() << std::endl; + * return next; + * } + * }; @endcode + * It would be used with the asio::connect function as follows: + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::socket s(io_service); + * + * // ... + * + * r.async_resolve(q, resolve_handler); + * + * // ... + * + * void resolve_handler( + * const asio::error_code& ec, + * tcp::resolver::iterator i) + * { + * if (!ec) + * { + * tcp::resolver::iterator end; + * asio::async_connect(s, i, end, + * my_connect_condition(), + * connect_handler); + * } + * } + * + * // ... + * + * void connect_handler( + * const asio::error_code& ec, + * tcp::resolver::iterator i) + * { + * if (ec) + * { + * // An error occurred. + * } + * else + * { + * std::cout << "Connected to: " << i->endpoint() << std::endl; + * } + * } @endcode + */ +template <typename Protocol, typename SocketService, typename Iterator, + typename ConnectCondition, typename ComposedConnectHandler> +ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler, + void (asio::error_code, Iterator)) +async_connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, Iterator end, ConnectCondition connect_condition, + ASIO_MOVE_ARG(ComposedConnectHandler) handler); + +/*@}*/ + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#include "asio/impl/connect.hpp" + +#endif diff --git a/asio-1.10.6/include/asio/detail/addressof.hpp b/asio-1.10.6/include/asio/detail/addressof.hpp new file mode 100644 index 0000000..63fb6f6 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/addressof.hpp @@ -0,0 +1,27 @@ +// +// detail/addressof.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_ADDRESSOF_HPP +#define ASIO_DETAIL_ADDRESSOF_HPP + + +#include "asio/detail/config.hpp" + +# include <memory> + +namespace asio { +namespace detail { + +using std::addressof; + +} // namespace detail +} // namespace asio + +#endif // ASIO_DETAIL_ADDRESSOF_HPP diff --git a/asio-1.10.6/include/asio/detail/array.hpp b/asio-1.10.6/include/asio/detail/array.hpp new file mode 100644 index 0000000..07590f2 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/array.hpp @@ -0,0 +1,27 @@ +// +// detail/array.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_ARRAY_HPP +#define ASIO_DETAIL_ARRAY_HPP + + +#include "asio/detail/config.hpp" + +# include <array> + +namespace asio { +namespace detail { + +using std::array; + +} // namespace detail +} // namespace asio + +#endif // ASIO_DETAIL_ARRAY_HPP diff --git a/asio-1.10.6/include/asio/detail/array_fwd.hpp b/asio-1.10.6/include/asio/detail/array_fwd.hpp new file mode 100644 index 0000000..59fa044 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/array_fwd.hpp @@ -0,0 +1,29 @@ +// +// detail/array_fwd.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_ARRAY_FWD_HPP +#define ASIO_DETAIL_ARRAY_FWD_HPP + + +#include "asio/detail/config.hpp" + +namespace boost { + +template<class T, std::size_t N> +class array; + +} // namespace boost + +// Standard library components can't be forward declared, so we'll have to +// include the array header. Fortunately, it's fairly lightweight and doesn't +// add significantly to the compile time. +# include <array> + +#endif // ASIO_DETAIL_ARRAY_FWD_HPP diff --git a/asio-1.10.6/include/asio/detail/assert.hpp b/asio-1.10.6/include/asio/detail/assert.hpp new file mode 100644 index 0000000..8dbe535 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/assert.hpp @@ -0,0 +1,21 @@ +// +// detail/assert.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_ASSERT_HPP +#define ASIO_DETAIL_ASSERT_HPP + + +#include "asio/detail/config.hpp" + +# include <cassert> + +# define ASIO_ASSERT(expr) assert(expr) + +#endif // ASIO_DETAIL_ASSERT_HPP diff --git a/asio-1.10.6/include/asio/detail/atomic_count.hpp b/asio-1.10.6/include/asio/detail/atomic_count.hpp new file mode 100644 index 0000000..170ec31 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/atomic_count.hpp @@ -0,0 +1,28 @@ +// +// detail/atomic_count.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_ATOMIC_COUNT_HPP +#define ASIO_DETAIL_ATOMIC_COUNT_HPP + + +#include "asio/detail/config.hpp" + +# include <atomic> + +namespace asio { +namespace detail { + +typedef std::atomic<long> atomic_count; +inline void increment(atomic_count& a, long b) { a += b; } + +} // namespace detail +} // namespace asio + +#endif // ASIO_DETAIL_ATOMIC_COUNT_HPP diff --git a/asio-1.10.6/include/asio/detail/base_from_completion_cond.hpp b/asio-1.10.6/include/asio/detail/base_from_completion_cond.hpp new file mode 100644 index 0000000..03bb94b --- /dev/null +++ b/asio-1.10.6/include/asio/detail/base_from_completion_cond.hpp @@ -0,0 +1,65 @@ +// +// detail/base_from_completion_cond.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_BASE_FROM_COMPLETION_COND_HPP +#define ASIO_DETAIL_BASE_FROM_COMPLETION_COND_HPP + + +#include "asio/detail/config.hpp" +#include "asio/completion_condition.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename CompletionCondition> +class base_from_completion_cond +{ +protected: + explicit base_from_completion_cond(CompletionCondition completion_condition) + : completion_condition_(completion_condition) + { + } + + std::size_t check_for_completion( + const asio::error_code& ec, + std::size_t total_transferred) + { + return detail::adapt_completion_condition_result( + completion_condition_(ec, total_transferred)); + } + +private: + CompletionCondition completion_condition_; +}; + +template <> +class base_from_completion_cond<transfer_all_t> +{ +protected: + explicit base_from_completion_cond(transfer_all_t) + { + } + + static std::size_t check_for_completion( + const asio::error_code& ec, + std::size_t total_transferred) + { + return transfer_all_t()(ec, total_transferred); + } +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_BASE_FROM_COMPLETION_COND_HPP diff --git a/asio-1.10.6/include/asio/detail/bind_handler.hpp b/asio-1.10.6/include/asio/detail/bind_handler.hpp new file mode 100644 index 0000000..00c87c5 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/bind_handler.hpp @@ -0,0 +1,486 @@ +// +// detail/bind_handler.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_BIND_HANDLER_HPP +#define ASIO_DETAIL_BIND_HANDLER_HPP + + +#include "asio/detail/config.hpp" +#include "asio/detail/handler_alloc_helpers.hpp" +#include "asio/detail/handler_cont_helpers.hpp" +#include "asio/detail/handler_invoke_helpers.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename Handler, typename Arg1> +class binder1 +{ +public: + binder1(const Handler& handler, const Arg1& arg1) + : handler_(handler), + arg1_(arg1) + { + } + + binder1(Handler& handler, const Arg1& arg1) + : handler_(ASIO_MOVE_CAST(Handler)(handler)), + arg1_(arg1) + { + } + + void operator()() + { + handler_(static_cast<const Arg1&>(arg1_)); + } + + void operator()() const + { + handler_(arg1_); + } + +//private: + Handler handler_; + Arg1 arg1_; +}; + +template <typename Handler, typename Arg1> +inline void* asio_handler_allocate(std::size_t size, + binder1<Handler, Arg1>* this_handler) +{ + return asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); +} + +template <typename Handler, typename Arg1> +inline void asio_handler_deallocate(void* pointer, std::size_t size, + binder1<Handler, Arg1>* this_handler) +{ + asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); +} + +template <typename Handler, typename Arg1> +inline bool asio_handler_is_continuation( + binder1<Handler, Arg1>* this_handler) +{ + return asio_handler_cont_helpers::is_continuation( + this_handler->handler_); +} + +template <typename Function, typename Handler, typename Arg1> +inline void asio_handler_invoke(Function& function, + binder1<Handler, Arg1>* this_handler) +{ + asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); +} + +template <typename Function, typename Handler, typename Arg1> +inline void asio_handler_invoke(const Function& function, + binder1<Handler, Arg1>* this_handler) +{ + asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); +} + +template <typename Handler, typename Arg1> +inline binder1<Handler, Arg1> bind_handler(Handler handler, + const Arg1& arg1) +{ + return binder1<Handler, Arg1>(handler, arg1); +} + +template <typename Handler, typename Arg1, typename Arg2> +class binder2 +{ +public: + binder2(const Handler& handler, const Arg1& arg1, const Arg2& arg2) + : handler_(handler), + arg1_(arg1), + arg2_(arg2) + { + } + + binder2(Handler& handler, const Arg1& arg1, const Arg2& arg2) + : handler_(ASIO_MOVE_CAST(Handler)(handler)), + arg1_(arg1), + arg2_(arg2) + { + } + + void operator()() + { + handler_(static_cast<const Arg1&>(arg1_), + static_cast<const Arg2&>(arg2_)); + } + + void operator()() const + { + handler_(arg1_, arg2_); + } + +//private: + Handler handler_; + Arg1 arg1_; + Arg2 arg2_; +}; + +template <typename Handler, typename Arg1, typename Arg2> +inline void* asio_handler_allocate(std::size_t size, + binder2<Handler, Arg1, Arg2>* this_handler) +{ + return asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); +} + +template <typename Handler, typename Arg1, typename Arg2> +inline void asio_handler_deallocate(void* pointer, std::size_t size, + binder2<Handler, Arg1, Arg2>* this_handler) +{ + asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); +} + +template <typename Handler, typename Arg1, typename Arg2> +inline bool asio_handler_is_continuation( + binder2<Handler, Arg1, Arg2>* this_handler) +{ + return asio_handler_cont_helpers::is_continuation( + this_handler->handler_); +} + +template <typename Function, typename Handler, typename Arg1, typename Arg2> +inline void asio_handler_invoke(Function& function, + binder2<Handler, Arg1, Arg2>* this_handler) +{ + asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); +} + +template <typename Function, typename Handler, typename Arg1, typename Arg2> +inline void asio_handler_invoke(const Function& function, + binder2<Handler, Arg1, Arg2>* this_handler) +{ + asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); +} + +template <typename Handler, typename Arg1, typename Arg2> +inline binder2<Handler, Arg1, Arg2> bind_handler(Handler handler, + const Arg1& arg1, const Arg2& arg2) +{ + return binder2<Handler, Arg1, Arg2>(handler, arg1, arg2); +} + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3> +class binder3 +{ +public: + binder3(const Handler& handler, const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3) + : handler_(handler), + arg1_(arg1), + arg2_(arg2), + arg3_(arg3) + { + } + + binder3(Handler& handler, const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3) + : handler_(ASIO_MOVE_CAST(Handler)(handler)), + arg1_(arg1), + arg2_(arg2), + arg3_(arg3) + { + } + + void operator()() + { + handler_(static_cast<const Arg1&>(arg1_), + static_cast<const Arg2&>(arg2_), + static_cast<const Arg3&>(arg3_)); + } + + void operator()() const + { + handler_(arg1_, arg2_, arg3_); + } + +//private: + Handler handler_; + Arg1 arg1_; + Arg2 arg2_; + Arg3 arg3_; +}; + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3> +inline void* asio_handler_allocate(std::size_t size, + binder3<Handler, Arg1, Arg2, Arg3>* this_handler) +{ + return asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); +} + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3> +inline void asio_handler_deallocate(void* pointer, std::size_t size, + binder3<Handler, Arg1, Arg2, Arg3>* this_handler) +{ + asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); +} + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3> +inline bool asio_handler_is_continuation( + binder3<Handler, Arg1, Arg2, Arg3>* this_handler) +{ + return asio_handler_cont_helpers::is_continuation( + this_handler->handler_); +} + +template <typename Function, typename Handler, typename Arg1, typename Arg2, + typename Arg3> +inline void asio_handler_invoke(Function& function, + binder3<Handler, Arg1, Arg2, Arg3>* this_handler) +{ + asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); +} + +template <typename Function, typename Handler, typename Arg1, typename Arg2, + typename Arg3> +inline void asio_handler_invoke(const Function& function, + binder3<Handler, Arg1, Arg2, Arg3>* this_handler) +{ + asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); +} + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3> +inline binder3<Handler, Arg1, Arg2, Arg3> bind_handler(Handler handler, + const Arg1& arg1, const Arg2& arg2, const Arg3& arg3) +{ + return binder3<Handler, Arg1, Arg2, Arg3>(handler, arg1, arg2, arg3); +} + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3, + typename Arg4> +class binder4 +{ +public: + binder4(const Handler& handler, const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3, const Arg4& arg4) + : handler_(handler), + arg1_(arg1), + arg2_(arg2), + arg3_(arg3), + arg4_(arg4) + { + } + + binder4(Handler& handler, const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3, const Arg4& arg4) + : handler_(ASIO_MOVE_CAST(Handler)(handler)), + arg1_(arg1), + arg2_(arg2), + arg3_(arg3), + arg4_(arg4) + { + } + + void operator()() + { + handler_(static_cast<const Arg1&>(arg1_), + static_cast<const Arg2&>(arg2_), + static_cast<const Arg3&>(arg3_), + static_cast<const Arg4&>(arg4_)); + } + + void operator()() const + { + handler_(arg1_, arg2_, arg3_, arg4_); + } + +//private: + Handler handler_; + Arg1 arg1_; + Arg2 arg2_; + Arg3 arg3_; + Arg4 arg4_; +}; + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3, + typename Arg4> +inline void* asio_handler_allocate(std::size_t size, + binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler) +{ + return asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); +} + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3, + typename Arg4> +inline void asio_handler_deallocate(void* pointer, std::size_t size, + binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler) +{ + asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); +} + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3, + typename Arg4> +inline bool asio_handler_is_continuation( + binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler) +{ + return asio_handler_cont_helpers::is_continuation( + this_handler->handler_); +} + +template <typename Function, typename Handler, typename Arg1, typename Arg2, + typename Arg3, typename Arg4> +inline void asio_handler_invoke(Function& function, + binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler) +{ + asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); +} + +template <typename Function, typename Handler, typename Arg1, typename Arg2, + typename Arg3, typename Arg4> +inline void asio_handler_invoke(const Function& function, + binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler) +{ + asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); +} + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3, + typename Arg4> +inline binder4<Handler, Arg1, Arg2, Arg3, Arg4> bind_handler( + Handler handler, const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3, const Arg4& arg4) +{ + return binder4<Handler, Arg1, Arg2, Arg3, Arg4>(handler, arg1, arg2, arg3, + arg4); +} + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3, + typename Arg4, typename Arg5> +class binder5 +{ +public: + binder5(const Handler& handler, const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3, const Arg4& arg4, const Arg5& arg5) + : handler_(handler), + arg1_(arg1), + arg2_(arg2), + arg3_(arg3), + arg4_(arg4), + arg5_(arg5) + { + } + + binder5(Handler& handler, const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3, const Arg4& arg4, const Arg5& arg5) + : handler_(ASIO_MOVE_CAST(Handler)(handler)), + arg1_(arg1), + arg2_(arg2), + arg3_(arg3), + arg4_(arg4), + arg5_(arg5) + { + } + + void operator()() + { + handler_(static_cast<const Arg1&>(arg1_), + static_cast<const Arg2&>(arg2_), + static_cast<const Arg3&>(arg3_), + static_cast<const Arg4&>(arg4_), + static_cast<const Arg5&>(arg5_)); + } + + void operator()() const + { + handler_(arg1_, arg2_, arg3_, arg4_, arg5_); + } + +//private: + Handler handler_; + Arg1 arg1_; + Arg2 arg2_; + Arg3 arg3_; + Arg4 arg4_; + Arg5 arg5_; +}; + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3, + typename Arg4, typename Arg5> +inline void* asio_handler_allocate(std::size_t size, + binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler) +{ + return asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); +} + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3, + typename Arg4, typename Arg5> +inline void asio_handler_deallocate(void* pointer, std::size_t size, + binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler) +{ + asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); +} + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3, + typename Arg4, typename Arg5> +inline bool asio_handler_is_continuation( + binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler) +{ + return asio_handler_cont_helpers::is_continuation( + this_handler->handler_); +} + +template <typename Function, typename Handler, typename Arg1, typename Arg2, + typename Arg3, typename Arg4, typename Arg5> +inline void asio_handler_invoke(Function& function, + binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler) +{ + asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); +} + +template <typename Function, typename Handler, typename Arg1, typename Arg2, + typename Arg3, typename Arg4, typename Arg5> +inline void asio_handler_invoke(const Function& function, + binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler) +{ + asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); +} + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3, + typename Arg4, typename Arg5> +inline binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5> bind_handler( + Handler handler, const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3, const Arg4& arg4, const Arg5& arg5) +{ + return binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>(handler, arg1, arg2, + arg3, arg4, arg5); +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_BIND_HANDLER_HPP diff --git a/asio-1.10.6/include/asio/detail/buffer_sequence_adapter.hpp b/asio-1.10.6/include/asio/detail/buffer_sequence_adapter.hpp new file mode 100644 index 0000000..9c463b8 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/buffer_sequence_adapter.hpp @@ -0,0 +1,342 @@ +// +// detail/buffer_sequence_adapter.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP +#define ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP + + +#include "asio/detail/config.hpp" +#include "asio/buffer.hpp" +#include "asio/detail/array_fwd.hpp" +#include "asio/detail/socket_types.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class buffer_sequence_adapter_base +{ +protected: + // The maximum number of buffers to support in a single operation. + enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len }; + + typedef iovec native_buffer_type; + + static void init_iov_base(void*& base, void* addr) + { + base = addr; + } + + template <typename T> + static void init_iov_base(T& base, void* addr) + { + base = static_cast<T>(addr); + } + + static void init_native_buffer(iovec& iov, + const asio::mutable_buffer& buffer) + { + init_iov_base(iov.iov_base, asio::buffer_cast<void*>(buffer)); + iov.iov_len = asio::buffer_size(buffer); + } + + static void init_native_buffer(iovec& iov, + const asio::const_buffer& buffer) + { + init_iov_base(iov.iov_base, const_cast<void*>( + asio::buffer_cast<const void*>(buffer))); + iov.iov_len = asio::buffer_size(buffer); + } +}; + +// Helper class to translate buffers into the native buffer representation. +template <typename Buffer, typename Buffers> +class buffer_sequence_adapter + : buffer_sequence_adapter_base +{ +public: + explicit buffer_sequence_adapter(const Buffers& buffer_sequence) + : count_(0), total_buffer_size_(0) + { + typename Buffers::const_iterator iter = buffer_sequence.begin(); + typename Buffers::const_iterator end = buffer_sequence.end(); + for (; iter != end && count_ < max_buffers; ++iter, ++count_) + { + Buffer buffer(*iter); + init_native_buffer(buffers_[count_], buffer); + total_buffer_size_ += asio::buffer_size(buffer); + } + } + + native_buffer_type* buffers() + { + return buffers_; + } + + std::size_t count() const + { + return count_; + } + + bool all_empty() const + { + return total_buffer_size_ == 0; + } + + static bool all_empty(const Buffers& buffer_sequence) + { + typename Buffers::const_iterator iter = buffer_sequence.begin(); + typename Buffers::const_iterator end = buffer_sequence.end(); + std::size_t i = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + if (asio::buffer_size(Buffer(*iter)) > 0) + return false; + return true; + } + + static void validate(const Buffers& buffer_sequence) + { + typename Buffers::const_iterator iter = buffer_sequence.begin(); + typename Buffers::const_iterator end = buffer_sequence.end(); + for (; iter != end; ++iter) + { + Buffer buffer(*iter); + asio::buffer_cast<const void*>(buffer); + } + } + + static Buffer first(const Buffers& buffer_sequence) + { + typename Buffers::const_iterator iter = buffer_sequence.begin(); + typename Buffers::const_iterator end = buffer_sequence.end(); + for (; iter != end; ++iter) + { + Buffer buffer(*iter); + if (asio::buffer_size(buffer) != 0) + return buffer; + } + return Buffer(); + } + +private: + native_buffer_type buffers_[max_buffers]; + std::size_t count_; + std::size_t total_buffer_size_; +}; + +template <typename Buffer> +class buffer_sequence_adapter<Buffer, asio::mutable_buffers_1> + : buffer_sequence_adapter_base +{ +public: + explicit buffer_sequence_adapter( + const asio::mutable_buffers_1& buffer_sequence) + { + init_native_buffer(buffer_, Buffer(buffer_sequence)); + total_buffer_size_ = asio::buffer_size(buffer_sequence); + } + + native_buffer_type* buffers() + { + return &buffer_; + } + + std::size_t count() const + { + return 1; + } + + bool all_empty() const + { + return total_buffer_size_ == 0; + } + + static bool all_empty(const asio::mutable_buffers_1& buffer_sequence) + { + return asio::buffer_size(buffer_sequence) == 0; + } + + static void validate(const asio::mutable_buffers_1& buffer_sequence) + { + asio::buffer_cast<const void*>(buffer_sequence); + } + + static Buffer first(const asio::mutable_buffers_1& buffer_sequence) + { + return Buffer(buffer_sequence); + } + +private: + native_buffer_type buffer_; + std::size_t total_buffer_size_; +}; + +template <typename Buffer> +class buffer_sequence_adapter<Buffer, asio::const_buffers_1> + : buffer_sequence_adapter_base +{ +public: + explicit buffer_sequence_adapter( + const asio::const_buffers_1& buffer_sequence) + { + init_native_buffer(buffer_, Buffer(buffer_sequence)); + total_buffer_size_ = asio::buffer_size(buffer_sequence); + } + + native_buffer_type* buffers() + { + return &buffer_; + } + + std::size_t count() const + { + return 1; + } + + bool all_empty() const + { + return total_buffer_size_ == 0; + } + + static bool all_empty(const asio::const_buffers_1& buffer_sequence) + { + return asio::buffer_size(buffer_sequence) == 0; + } + + static void validate(const asio::const_buffers_1& buffer_sequence) + { + asio::buffer_cast<const void*>(buffer_sequence); + } + + static Buffer first(const asio::const_buffers_1& buffer_sequence) + { + return Buffer(buffer_sequence); + } + +private: + native_buffer_type buffer_; + std::size_t total_buffer_size_; +}; + +template <typename Buffer, typename Elem> +class buffer_sequence_adapter<Buffer, boost::array<Elem, 2> > + : buffer_sequence_adapter_base +{ +public: + explicit buffer_sequence_adapter( + const boost::array<Elem, 2>& buffer_sequence) + { + init_native_buffer(buffers_[0], Buffer(buffer_sequence[0])); + init_native_buffer(buffers_[1], Buffer(buffer_sequence[1])); + total_buffer_size_ = asio::buffer_size(buffer_sequence[0]) + + asio::buffer_size(buffer_sequence[1]); + } + + native_buffer_type* buffers() + { + return buffers_; + } + + std::size_t count() const + { + return 2; + } + + bool all_empty() const + { + return total_buffer_size_ == 0; + } + + static bool all_empty(const boost::array<Elem, 2>& buffer_sequence) + { + return asio::buffer_size(buffer_sequence[0]) == 0 + && asio::buffer_size(buffer_sequence[1]) == 0; + } + + static void validate(const boost::array<Elem, 2>& buffer_sequence) + { + asio::buffer_cast<const void*>(buffer_sequence[0]); + asio::buffer_cast<const void*>(buffer_sequence[1]); + } + + static Buffer first(const boost::array<Elem, 2>& buffer_sequence) + { + return Buffer(asio::buffer_size(buffer_sequence[0]) != 0 + ? buffer_sequence[0] : buffer_sequence[1]); + } + +private: + native_buffer_type buffers_[2]; + std::size_t total_buffer_size_; +}; + + +template <typename Buffer, typename Elem> +class buffer_sequence_adapter<Buffer, std::array<Elem, 2> > + : buffer_sequence_adapter_base +{ +public: + explicit buffer_sequence_adapter( + const std::array<Elem, 2>& buffer_sequence) + { + init_native_buffer(buffers_[0], Buffer(buffer_sequence[0])); + init_native_buffer(buffers_[1], Buffer(buffer_sequence[1])); + total_buffer_size_ = asio::buffer_size(buffer_sequence[0]) + + asio::buffer_size(buffer_sequence[1]); + } + + native_buffer_type* buffers() + { + return buffers_; + } + + std::size_t count() const + { + return 2; + } + + bool all_empty() const + { + return total_buffer_size_ == 0; + } + + static bool all_empty(const std::array<Elem, 2>& buffer_sequence) + { + return asio::buffer_size(buffer_sequence[0]) == 0 + && asio::buffer_size(buffer_sequence[1]) == 0; + } + + static void validate(const std::array<Elem, 2>& buffer_sequence) + { + asio::buffer_cast<const void*>(buffer_sequence[0]); + asio::buffer_cast<const void*>(buffer_sequence[1]); + } + + static Buffer first(const std::array<Elem, 2>& buffer_sequence) + { + return Buffer(asio::buffer_size(buffer_sequence[0]) != 0 + ? buffer_sequence[0] : buffer_sequence[1]); + } + +private: + native_buffer_type buffers_[2]; + std::size_t total_buffer_size_; +}; + + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +# include "asio/detail/impl/buffer_sequence_adapter.ipp" + +#endif // ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP diff --git a/asio-1.10.6/include/asio/detail/call_stack.hpp b/asio-1.10.6/include/asio/detail/call_stack.hpp new file mode 100644 index 0000000..1c005eb --- /dev/null +++ b/asio-1.10.6/include/asio/detail/call_stack.hpp @@ -0,0 +1,122 @@ +// +// detail/call_stack.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_CALL_STACK_HPP +#define ASIO_DETAIL_CALL_STACK_HPP + + +#include "asio/detail/config.hpp" +#include "asio/detail/noncopyable.hpp" +#include "asio/detail/tss_ptr.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +// Helper class to determine whether or not the current thread is inside an +// invocation of io_service::run() for a specified io_service object. +template <typename Key, typename Value = unsigned char> +class call_stack +{ +public: + // Context class automatically pushes the key/value pair on to the stack. + class context + : private noncopyable + { + public: + // Push the key on to the stack. + explicit context(Key* k) + : key_(k), + next_(call_stack<Key, Value>::top_) + { + value_ = reinterpret_cast<unsigned char*>(this); + call_stack<Key, Value>::top_ = this; + } + + // Push the key/value pair on to the stack. + context(Key* k, Value& v) + : key_(k), + value_(&v), + next_(call_stack<Key, Value>::top_) + { + call_stack<Key, Value>::top_ = this; + } + + // Pop the key/value pair from the stack. + ~context() + { + call_stack<Key, Value>::top_ = next_; + } + + // Find the next context with the same key. + Value* next_by_key() const + { + context* elem = next_; + while (elem) + { + if (elem->key_ == key_) + return elem->value_; + elem = elem->next_; + } + return 0; + } + + private: + friend class call_stack<Key, Value>; + + // The key associated with the context. + Key* key_; + + // The value associated with the context. + Value* value_; + + // The next element in the stack. + context* next_; + }; + + friend class context; + + // Determine whether the specified owner is on the stack. Returns address of + // key if present, 0 otherwise. + static Value* contains(Key* k) + { + context* elem = top_; + while (elem) + { + if (elem->key_ == k) + return elem->value_; + elem = elem->next_; + } + return 0; + } + + // Obtain the value at the top of the stack. + static Value* top() + { + context* elem = top_; + return elem ? elem->value_ : 0; + } + +private: + // The top of the stack of calls for the current thread. + static tss_ptr<context> top_; +}; + +template <typename Key, typename Value> +tss_ptr<typename call_stack<Key, Value>::context> +call_stack<Key, Value>::top_; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_CALL_STACK_HPP diff --git a/asio-1.10.6/include/asio/detail/completion_handler.hpp b/asio-1.10.6/include/asio/detail/completion_handler.hpp new file mode 100644 index 0000000..75c11f2 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/completion_handler.hpp @@ -0,0 +1,78 @@ +// +// detail/completion_handler.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_COMPLETION_HANDLER_HPP +#define ASIO_DETAIL_COMPLETION_HANDLER_HPP + + +#include "asio/detail/addressof.hpp" +#include "asio/detail/config.hpp" +#include "asio/detail/fenced_block.hpp" +#include "asio/detail/handler_alloc_helpers.hpp" +#include "asio/detail/handler_invoke_helpers.hpp" +#include "asio/detail/operation.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename Handler> +class completion_handler : public operation +{ +public: + ASIO_DEFINE_HANDLER_PTR(completion_handler); + + completion_handler(Handler& h) + : operation(&completion_handler::do_complete), + handler_(ASIO_MOVE_CAST(Handler)(h)) + { + } + + static void do_complete(io_service_impl* owner, operation* base, + const asio::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + completion_handler* h(static_cast<completion_handler*>(base)); + ptr p = { asio::detail::addressof(h->handler_), h, h }; + + ASIO_HANDLER_COMPLETION((h)); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + Handler handler(ASIO_MOVE_CAST(Handler)(h->handler_)); + p.h = asio::detail::addressof(handler); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + ASIO_HANDLER_INVOCATION_BEGIN(()); + asio_handler_invoke_helpers::invoke(handler, handler); + ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_COMPLETION_HANDLER_HPP diff --git a/asio-1.10.6/include/asio/detail/config.hpp b/asio-1.10.6/include/asio/detail/config.hpp new file mode 100644 index 0000000..15797ee --- /dev/null +++ b/asio-1.10.6/include/asio/detail/config.hpp @@ -0,0 +1,306 @@ +// +// detail/config.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_CONFIG_HPP +#define ASIO_DETAIL_CONFIG_HPP + +# define ASIO_DISABLE_BOOST_ARRAY 1 +# define ASIO_DISABLE_BOOST_ASSERT 1 +# define ASIO_DISABLE_BOOST_BIND 1 +# define ASIO_DISABLE_BOOST_CHRONO 1 +# define ASIO_DISABLE_BOOST_DATE_TIME 1 +# define ASIO_DISABLE_BOOST_LIMITS 1 +# define ASIO_DISABLE_BOOST_REGEX 1 +# define ASIO_DISABLE_BOOST_STATIC_CONSTANT 1 +# define ASIO_DISABLE_BOOST_THROW_EXCEPTION 1 +# define ASIO_DISABLE_BOOST_WORKAROUND 1 + +// Default to a header-only implementation. The user must specifically request +// separate compilation by defining either ASIO_SEPARATE_COMPILATION or +// ASIO_DYN_LINK (as a DLL/shared library implies separate compilation). + +# define ASIO_DECL inline + +// If ASIO_DECL isn't defined yet define it now. +#if !defined(ASIO_DECL) +# define ASIO_DECL +#endif // !defined(ASIO_DECL) + +// Microsoft Visual C++ detection. + +// Clang / libc++ detection. +# if (__cplusplus >= 201103) +# if __has_include(<__config>) +# include <__config> +# if defined(_LIBCPP_VERSION) +# define ASIO_HAS_CLANG_LIBCXX 1 +# endif // defined(_LIBCPP_VERSION) +# endif // __has_include(<__config>) +# endif // (__cplusplus >= 201103) + +// Support move construction and assignment on compilers known to allow it. + +// If ASIO_MOVE_CAST isn't defined, and move support is available, define +// ASIO_MOVE_ARG and ASIO_MOVE_CAST to take advantage of rvalue +// references and perfect forwarding. +#if defined(ASIO_HAS_MOVE) && !defined(ASIO_MOVE_CAST) +# define ASIO_MOVE_ARG(type) type&& +# define ASIO_MOVE_CAST(type) static_cast<type&&> +# define ASIO_MOVE_CAST2(type1, type2) static_cast<type1, type2&&> +#endif // defined(ASIO_HAS_MOVE) && !defined(ASIO_MOVE_CAST) + +// If ASIO_MOVE_CAST still isn't defined, default to a C++03-compatible +// implementation. Note that older g++ and MSVC versions don't like it when you +// pass a non-member function through a const reference, so for most compilers +// we'll play it safe and stick with the old approach of passing the handler by +// value. +#if !defined(ASIO_MOVE_CAST) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1)) || (__GNUC__ > 4) +# define ASIO_MOVE_ARG(type) const type& +# else // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1)) || (__GNUC__ > 4) +# define ASIO_MOVE_ARG(type) type +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1)) || (__GNUC__ > 4) +# else +# define ASIO_MOVE_ARG(type) type +# endif +# define ASIO_MOVE_CAST(type) static_cast<const type&> +# define ASIO_MOVE_CAST2(type1, type2) static_cast<const type1, type2&> +#endif // !defined(ASIO_MOVE_CAST) + +// Support variadic templates on compilers known to allow it. + +// Support constexpr on compilers known to allow it. +#if !defined(ASIO_CONSTEXPR) +# define ASIO_CONSTEXPR constexpr +#endif // !defined(ASIO_CONSTEXPR) + +// Standard library support for system errors. + +// Compliant C++11 compilers put noexcept specifiers on error_category members. +#if !defined(ASIO_ERROR_CATEGORY_NOEXCEPT) +# if (BOOST_VERSION >= 105300) +# define ASIO_ERROR_CATEGORY_NOEXCEPT BOOST_NOEXCEPT +# else +# if __has_feature(__cxx_noexcept__) +# define ASIO_ERROR_CATEGORY_NOEXCEPT noexcept(true) +# endif // __has_feature(__cxx_noexcept__) +# endif +# if !defined(ASIO_ERROR_CATEGORY_NOEXCEPT) +# define ASIO_ERROR_CATEGORY_NOEXCEPT +# endif // !defined(ASIO_ERROR_CATEGORY_NOEXCEPT) +#endif // !defined(ASIO_ERROR_CATEGORY_NOEXCEPT) + +// Standard library support for arrays. + +// Standard library support for shared_ptr and weak_ptr. + +// Standard library support for atomic operations. + +// Standard library support for chrono. Some standard libraries (such as the +// libstdc++ shipped with gcc 4.6) provide monotonic_clock as per early C++0x +// drafts, rather than the eventually standardised name of steady_clock. + +// Boost support for chrono. + +// Boost support for the DateTime library. + +// Standard library support for addressof. + +// Standard library support for the function class. + +// Standard library support for type traits. + +// Standard library support for the cstdint header. + +// Standard library support for the thread class. + +// Standard library support for the mutex and condition variable classes. + +// WinRT target. +# if defined(__cplusplus_winrt) +# include <winapifamily.h> +# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +# define ASIO_WINDOWS_RUNTIME 1 +# endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) + // && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +# endif // defined(__cplusplus_winrt) + +// Windows target. Excludes WinRT. + +// Windows: target OS version. + +// Windows: minimise header inclusion. + +// Windows: suppress definition of "min" and "max" macros. + +// Windows: IO Completion Ports. + +// On POSIX (and POSIX-like) platforms we need to include unistd.h in order to +// get access to the various platform feature macros, e.g. to be able to test +// for threads support. +#if !defined(ASIO_HAS_UNISTD_H) +# if defined(unix) || defined(__unix) || defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE) || (defined(__MACH__) && defined(__APPLE__)) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__linux__) +# define ASIO_HAS_UNISTD_H 1 +# endif +#endif // !defined(ASIO_HAS_UNISTD_H) +#if defined(ASIO_HAS_UNISTD_H) +# include <unistd.h> +#endif // defined(ASIO_HAS_UNISTD_H) + +// Linux: epoll, eventfd and timerfd. +#if defined(__linux__) +# include <linux/version.h> +# if !defined(ASIO_HAS_EPOLL) +# endif // !defined(ASIO_HAS_EPOLL) +# if defined(ASIO_HAS_EPOLL) +# if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8) +# define ASIO_HAS_TIMERFD 1 +# endif // (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8) +# endif // defined(ASIO_HAS_EPOLL) +#endif // defined(__linux__) + +// Mac OS X, FreeBSD, NetBSD, OpenBSD: kqueue. +#if (defined(__MACH__) && defined(__APPLE__)) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) +#endif // (defined(__MACH__) && defined(__APPLE__)) + // || defined(__FreeBSD__) + // || defined(__NetBSD__) + // || defined(__OpenBSD__) + +// Solaris: /dev/poll. +#if defined(__sun) +# if !defined(ASIO_HAS_DEV_POLL) +# if !defined(ASIO_DISABLE_DEV_POLL) +# define ASIO_HAS_DEV_POLL 1 +# endif // !defined(ASIO_DISABLE_DEV_POLL) +# endif // !defined(ASIO_HAS_DEV_POLL) +#endif // defined(__sun) + +// Serial ports. + // || !defined(ASIO_WINDOWS) + // && !defined(ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) + +// Windows: stream handles. +# if !defined(ASIO_DISABLE_WINDOWS_STREAM_HANDLE) +# endif // !defined(ASIO_DISABLE_WINDOWS_STREAM_HANDLE) + +// Windows: random access handles. +# if !defined(ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE) +# endif // !defined(ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE) + +// Windows: object handles. +# if !defined(ASIO_DISABLE_WINDOWS_OBJECT_HANDLE) +# endif // !defined(ASIO_DISABLE_WINDOWS_OBJECT_HANDLE) + +// Windows: OVERLAPPED wrapper. +# if !defined(ASIO_DISABLE_WINDOWS_OVERLAPPED_PTR) +# endif // !defined(ASIO_DISABLE_WINDOWS_OVERLAPPED_PTR) + +// POSIX: stream-oriented file descriptors. + +// UNIX domain sockets. + +// Can use sigaction() instead of signal(). +#if !defined(ASIO_HAS_SIGACTION) +# if !defined(ASIO_DISABLE_SIGACTION) +# define ASIO_HAS_SIGACTION 1 + // && !defined(ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) +# endif // !defined(ASIO_DISABLE_SIGACTION) +#endif // !defined(ASIO_HAS_SIGACTION) + +// Can use signal(). +#if !defined(ASIO_HAS_SIGNAL) +# if !defined(ASIO_DISABLE_SIGNAL) +# if !defined(UNDER_CE) +# define ASIO_HAS_SIGNAL 1 +# endif // !defined(UNDER_CE) +# endif // !defined(ASIO_DISABLE_SIGNAL) +#endif // !defined(ASIO_HAS_SIGNAL) + +// Can use getaddrinfo() and getnameinfo(). + +// Whether standard iostreams are disabled. + +// Whether exception handling is disabled. +#if !defined(ASIO_NO_EXCEPTIONS) +#endif // !defined(ASIO_NO_EXCEPTIONS) + +// Whether the typeid operator is supported. +#if !defined(ASIO_NO_TYPEID) +#endif // !defined(ASIO_NO_TYPEID) + +// Threads. + +// POSIX threads. +#if !defined(ASIO_HAS_PTHREADS) +# if defined(_POSIX_THREADS) +# define ASIO_HAS_PTHREADS 1 +# endif // defined(ASIO_HAS_BOOST_CONFIG) && defined(BOOST_HAS_PTHREADS) +#endif // !defined(ASIO_HAS_PTHREADS) + +// Helper to prevent macro expansion. +#define ASIO_PREVENT_MACRO_SUBSTITUTION + +// Helper to define in-class constants. +#if !defined(ASIO_STATIC_CONSTANT) +# define ASIO_STATIC_CONSTANT(type, assignment) static const type assignment +#endif // !defined(ASIO_STATIC_CONSTANT) + +// Boost array library. + +// Boost assert macro. + +// Boost limits header. + +// Boost throw_exception function. + +// Boost regex library. + +// Boost bind function. + +// Boost's BOOST_WORKAROUND macro. + +// Microsoft Visual C++'s secure C runtime library. +#if !defined(ASIO_HAS_SECURE_RTL) +# if !defined(ASIO_DISABLE_SECURE_RTL) + // && (ASIO_MSVC >= 1400) + // && !defined(UNDER_CE) +# endif // !defined(ASIO_DISABLE_SECURE_RTL) +#endif // !defined(ASIO_HAS_SECURE_RTL) + +// Handler hooking. Disabled for ancient Borland C++ and gcc compilers. +#if !defined(ASIO_HAS_HANDLER_HOOKS) +# if !defined(ASIO_DISABLE_HANDLER_HOOKS) +# if defined(__GNUC__) +# if (__GNUC__ >= 3) +# define ASIO_HAS_HANDLER_HOOKS 1 +# endif // (__GNUC__ >= 3) +# else +# define ASIO_HAS_HANDLER_HOOKS 1 +# endif // !defined(__BORLANDC__) +# endif // !defined(ASIO_DISABLE_HANDLER_HOOKS) +#endif // !defined(ASIO_HAS_HANDLER_HOOKS) + +// Support for the __thread keyword extension. +#if !defined(ASIO_THREAD_KEYWORD) +# define ASIO_THREAD_KEYWORD __thread +#endif // !defined(ASIO_THREAD_KEYWORD) + +// Support for POSIX ssize_t typedef. +#if !defined(ASIO_DISABLE_SSIZE_T) +# if defined(__linux__) || (defined(__MACH__) && defined(__APPLE__)) +# define ASIO_HAS_SSIZE_T 1 +# endif // defined(__linux__) + // || (defined(__MACH__) && defined(__APPLE__)) +#endif // !defined(ASIO_DISABLE_SSIZE_T) + +#endif // ASIO_DETAIL_CONFIG_HPP diff --git a/asio-1.10.6/include/asio/detail/consuming_buffers.hpp b/asio-1.10.6/include/asio/detail/consuming_buffers.hpp new file mode 100644 index 0000000..79f1d24 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/consuming_buffers.hpp @@ -0,0 +1,289 @@ +// +// detail/consuming_buffers.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_CONSUMING_BUFFERS_HPP +#define ASIO_DETAIL_CONSUMING_BUFFERS_HPP + + +#include "asio/detail/config.hpp" +#include <cstddef> +#include <iterator> +#include "asio/buffer.hpp" +#include "asio/detail/limits.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +// A proxy iterator for a sub-range in a list of buffers. +template <typename Buffer, typename Buffer_Iterator> +class consuming_buffers_iterator +{ +public: + /// The type used for the distance between two iterators. + typedef std::ptrdiff_t difference_type; + + /// The type of the value pointed to by the iterator. + typedef Buffer value_type; + + /// The type of the result of applying operator->() to the iterator. + typedef const Buffer* pointer; + + /// The type of the result of applying operator*() to the iterator. + typedef const Buffer& reference; + + /// The iterator category. + typedef std::forward_iterator_tag iterator_category; + + // Default constructor creates an end iterator. + consuming_buffers_iterator() + : at_end_(true) + { + } + + // Construct with a buffer for the first entry and an iterator + // range for the remaining entries. + consuming_buffers_iterator(bool at_end, const Buffer& first, + Buffer_Iterator begin_remainder, Buffer_Iterator end_remainder, + std::size_t max_size) + : at_end_(max_size > 0 ? at_end : true), + first_(buffer(first, max_size)), + begin_remainder_(begin_remainder), + end_remainder_(end_remainder), + offset_(0), + max_size_(max_size) + { + } + + // Dereference an iterator. + const Buffer& operator*() const + { + return dereference(); + } + + // Dereference an iterator. + const Buffer* operator->() const + { + return &dereference(); + } + + // Increment operator (prefix). + consuming_buffers_iterator& operator++() + { + increment(); + return *this; + } + + // Increment operator (postfix). + consuming_buffers_iterator operator++(int) + { + consuming_buffers_iterator tmp(*this); + ++*this; + return tmp; + } + + // Test two iterators for equality. + friend bool operator==(const consuming_buffers_iterator& a, + const consuming_buffers_iterator& b) + { + return a.equal(b); + } + + // Test two iterators for inequality. + friend bool operator!=(const consuming_buffers_iterator& a, + const consuming_buffers_iterator& b) + { + return !a.equal(b); + } + +private: + void increment() + { + if (!at_end_) + { + if (begin_remainder_ == end_remainder_ + || offset_ + buffer_size(first_) >= max_size_) + { + at_end_ = true; + } + else + { + offset_ += buffer_size(first_); + first_ = buffer(*begin_remainder_++, max_size_ - offset_); + } + } + } + + bool equal(const consuming_buffers_iterator& other) const + { + if (at_end_ && other.at_end_) + return true; + return !at_end_ && !other.at_end_ + && buffer_cast<const void*>(first_) + == buffer_cast<const void*>(other.first_) + && buffer_size(first_) == buffer_size(other.first_) + && begin_remainder_ == other.begin_remainder_ + && end_remainder_ == other.end_remainder_; + } + + const Buffer& dereference() const + { + return first_; + } + + bool at_end_; + Buffer first_; + Buffer_Iterator begin_remainder_; + Buffer_Iterator end_remainder_; + std::size_t offset_; + std::size_t max_size_; +}; + +// A proxy for a sub-range in a list of buffers. +template <typename Buffer, typename Buffers> +class consuming_buffers +{ +public: + // The type for each element in the list of buffers. + typedef Buffer value_type; + + // A forward-only iterator type that may be used to read elements. + typedef consuming_buffers_iterator<Buffer, typename Buffers::const_iterator> + const_iterator; + + // Construct to represent the entire list of buffers. + consuming_buffers(const Buffers& buffers) + : buffers_(buffers), + at_end_(buffers_.begin() == buffers_.end()), + begin_remainder_(buffers_.begin()), + max_size_((std::numeric_limits<std::size_t>::max)()) + { + if (!at_end_) + { + first_ = *buffers_.begin(); + ++begin_remainder_; + } + } + + // Copy constructor. + consuming_buffers(const consuming_buffers& other) + : buffers_(other.buffers_), + at_end_(other.at_end_), + first_(other.first_), + begin_remainder_(buffers_.begin()), + max_size_(other.max_size_) + { + typename Buffers::const_iterator first = other.buffers_.begin(); + typename Buffers::const_iterator second = other.begin_remainder_; + std::advance(begin_remainder_, std::distance(first, second)); + } + + // Assignment operator. + consuming_buffers& operator=(const consuming_buffers& other) + { + buffers_ = other.buffers_; + at_end_ = other.at_end_; + first_ = other.first_; + begin_remainder_ = buffers_.begin(); + typename Buffers::const_iterator first = other.buffers_.begin(); + typename Buffers::const_iterator second = other.begin_remainder_; + std::advance(begin_remainder_, std::distance(first, second)); + max_size_ = other.max_size_; + return *this; + } + + // Get a forward-only iterator to the first element. + const_iterator begin() const + { + return const_iterator(at_end_, first_, + begin_remainder_, buffers_.end(), max_size_); + } + + // Get a forward-only iterator for one past the last element. + const_iterator end() const + { + return const_iterator(); + } + + // Set the maximum size for a single transfer. + void prepare(std::size_t max_size) + { + max_size_ = max_size; + } + + // Consume the specified number of bytes from the buffers. + void consume(std::size_t size) + { + // Remove buffers from the start until the specified size is reached. + while (size > 0 && !at_end_) + { + if (buffer_size(first_) <= size) + { + size -= buffer_size(first_); + if (begin_remainder_ == buffers_.end()) + at_end_ = true; + else + first_ = *begin_remainder_++; + } + else + { + first_ = first_ + size; + size = 0; + } + } + + // Remove any more empty buffers at the start. + while (!at_end_ && buffer_size(first_) == 0) + { + if (begin_remainder_ == buffers_.end()) + at_end_ = true; + else + first_ = *begin_remainder_++; + } + } + +private: + Buffers buffers_; + bool at_end_; + Buffer first_; + typename Buffers::const_iterator begin_remainder_; + std::size_t max_size_; +}; + +// Specialisation for null_buffers to ensure that the null_buffers type is +// always passed through to the underlying read or write operation. +template <typename Buffer> +class consuming_buffers<Buffer, asio::null_buffers> + : public asio::null_buffers +{ +public: + consuming_buffers(const asio::null_buffers&) + { + // No-op. + } + + void prepare(std::size_t) + { + // No-op. + } + + void consume(std::size_t) + { + // No-op. + } +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_CONSUMING_BUFFERS_HPP diff --git a/asio-1.10.6/include/asio/detail/dependent_type.hpp b/asio-1.10.6/include/asio/detail/dependent_type.hpp new file mode 100644 index 0000000..b62a68d --- /dev/null +++ b/asio-1.10.6/include/asio/detail/dependent_type.hpp @@ -0,0 +1,33 @@ +// +// detail/dependent_type.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_DEPENDENT_TYPE_HPP +#define ASIO_DETAIL_DEPENDENT_TYPE_HPP + + +#include "asio/detail/config.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename DependsOn, typename T> +struct dependent_type +{ + typedef T type; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_DEPENDENT_TYPE_HPP diff --git a/asio-1.10.6/include/asio/detail/event.hpp b/asio-1.10.6/include/asio/detail/event.hpp new file mode 100644 index 0000000..9800e0f --- /dev/null +++ b/asio-1.10.6/include/asio/detail/event.hpp @@ -0,0 +1,35 @@ +// +// detail/event.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_EVENT_HPP +#define ASIO_DETAIL_EVENT_HPP + + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_PTHREADS) +# include "asio/detail/posix_event.hpp" +#else +# include "asio/detail/std_event.hpp" +#endif + +namespace asio { +namespace detail { + +#if defined(ASIO_HAS_PTHREADS) +typedef posix_event event; +#else +typedef std_event event; +#endif + +} // namespace detail +} // namespace asio + +#endif // ASIO_DETAIL_EVENT_HPP diff --git a/asio-1.10.6/include/asio/detail/fd_set_adapter.hpp b/asio-1.10.6/include/asio/detail/fd_set_adapter.hpp new file mode 100644 index 0000000..3033f43 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/fd_set_adapter.hpp @@ -0,0 +1,30 @@ +// +// detail/fd_set_adapter.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_FD_SET_ADAPTER_HPP +#define ASIO_DETAIL_FD_SET_ADAPTER_HPP + + +#include "asio/detail/config.hpp" + + +#include "asio/detail/posix_fd_set_adapter.hpp" +#include "asio/detail/win_fd_set_adapter.hpp" + +namespace asio { +namespace detail { + +typedef posix_fd_set_adapter fd_set_adapter; + +} // namespace detail +} // namespace asio + + +#endif // ASIO_DETAIL_FD_SET_ADAPTER_HPP diff --git a/asio-1.10.6/include/asio/detail/fenced_block.hpp b/asio-1.10.6/include/asio/detail/fenced_block.hpp new file mode 100644 index 0000000..5b5b824 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/fenced_block.hpp @@ -0,0 +1,59 @@ +// +// detail/fenced_block.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_FENCED_BLOCK_HPP +#define ASIO_DETAIL_FENCED_BLOCK_HPP + + +#include "asio/detail/config.hpp" + +#if !defined(ASIO_HAS_THREADS) || defined(ASIO_DISABLE_FENCED_BLOCK) +# include "asio/detail/null_fenced_block.hpp" +#elif defined(__MACH__) && defined(__APPLE__) +# include "asio/detail/macos_fenced_block.hpp" +#elif defined(__sun) +# include "asio/detail/solaris_fenced_block.hpp" +#elif defined(__GNUC__) && defined(__arm__) && !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) +# include "asio/detail/gcc_arm_fenced_block.hpp" +#elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__)) +# include "asio/detail/gcc_hppa_fenced_block.hpp" +#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +# include "asio/detail/gcc_x86_fenced_block.hpp" +#elif defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) && !defined(__INTEL_COMPILER) && !defined(__ICL) && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) +# include "asio/detail/gcc_sync_fenced_block.hpp" +#else +# include "asio/detail/null_fenced_block.hpp" +#endif + +namespace asio { +namespace detail { + +#if !defined(ASIO_HAS_THREADS) || defined(ASIO_DISABLE_FENCED_BLOCK) +typedef null_fenced_block fenced_block; +#elif defined(__MACH__) && defined(__APPLE__) +typedef macos_fenced_block fenced_block; +#elif defined(__sun) +typedef solaris_fenced_block fenced_block; +#elif defined(__GNUC__) && defined(__arm__) && !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) +typedef gcc_arm_fenced_block fenced_block; +#elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__)) +typedef gcc_hppa_fenced_block fenced_block; +#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +typedef gcc_x86_fenced_block fenced_block; +#elif defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) && !defined(__INTEL_COMPILER) && !defined(__ICL) && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) +typedef gcc_sync_fenced_block fenced_block; +#else +typedef null_fenced_block fenced_block; +#endif + +} // namespace detail +} // namespace asio + +#endif // ASIO_DETAIL_FENCED_BLOCK_HPP diff --git a/asio-1.10.6/include/asio/detail/handler_alloc_helpers.hpp b/asio-1.10.6/include/asio/detail/handler_alloc_helpers.hpp new file mode 100644 index 0000000..9386fdf --- /dev/null +++ b/asio-1.10.6/include/asio/detail/handler_alloc_helpers.hpp @@ -0,0 +1,55 @@ +// +// detail/handler_alloc_helpers.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP +#define ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP + + +#include "asio/detail/config.hpp" +#include "asio/detail/addressof.hpp" +#include "asio/detail/noncopyable.hpp" +#include "asio/handler_alloc_hook.hpp" + +#include "asio/detail/push_options.hpp" + +// Calls to asio_handler_allocate and asio_handler_deallocate must be made from +// a namespace that does not contain any overloads of these functions. The +// asio_handler_alloc_helpers namespace is defined here for that purpose. +namespace asio_handler_alloc_helpers { + +template <typename Handler> +inline void* allocate(std::size_t s, Handler& h) +{ +#if !defined(ASIO_HAS_HANDLER_HOOKS) + return ::operator new(s); +#else + using asio::asio_handler_allocate; + return asio_handler_allocate(s, asio::detail::addressof(h)); +#endif +} + +template <typename Handler> +inline void deallocate(void* p, std::size_t s, Handler& h) +{ +#if !defined(ASIO_HAS_HANDLER_HOOKS) + ::operator delete(p); +#else + using asio::asio_handler_deallocate; + asio_handler_deallocate(p, s, asio::detail::addressof(h)); +#endif +} + +} // namespace asio_handler_alloc_helpers + +#define ASIO_DEFINE_HANDLER_PTR(op) struct ptr { Handler* h; void* v; op* p; ~ptr() { reset(); } void reset() { if (p) { p->~op(); p = 0; } if (v) { asio_handler_alloc_helpers::deallocate(v, sizeof(op), *h); v = 0; } } } /**/ + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP diff --git a/asio-1.10.6/include/asio/detail/handler_cont_helpers.hpp b/asio-1.10.6/include/asio/detail/handler_cont_helpers.hpp new file mode 100644 index 0000000..319c0e2 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/handler_cont_helpers.hpp @@ -0,0 +1,42 @@ +// +// detail/handler_cont_helpers.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_HANDLER_CONT_HELPERS_HPP +#define ASIO_DETAIL_HANDLER_CONT_HELPERS_HPP + + +#include "asio/detail/config.hpp" +#include "asio/detail/addressof.hpp" +#include "asio/handler_continuation_hook.hpp" + +#include "asio/detail/push_options.hpp" + +// Calls to asio_handler_is_continuation must be made from a namespace that +// does not contain overloads of this function. This namespace is defined here +// for that purpose. +namespace asio_handler_cont_helpers { + +template <typename Context> +inline bool is_continuation(Context& context) +{ +#if !defined(ASIO_HAS_HANDLER_HOOKS) + return false; +#else + using asio::asio_handler_is_continuation; + return asio_handler_is_continuation( + asio::detail::addressof(context)); +#endif +} + +} // namespace asio_handler_cont_helpers + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_HANDLER_CONT_HELPERS_HPP diff --git a/asio-1.10.6/include/asio/detail/handler_invoke_helpers.hpp b/asio-1.10.6/include/asio/detail/handler_invoke_helpers.hpp new file mode 100644 index 0000000..f1ec530 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/handler_invoke_helpers.hpp @@ -0,0 +1,54 @@ +// +// detail/handler_invoke_helpers.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP +#define ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP + + +#include "asio/detail/config.hpp" +#include "asio/detail/addressof.hpp" +#include "asio/handler_invoke_hook.hpp" + +#include "asio/detail/push_options.hpp" + +// Calls to asio_handler_invoke must be made from a namespace that does not +// contain overloads of this function. The asio_handler_invoke_helpers +// namespace is defined here for that purpose. +namespace asio_handler_invoke_helpers { + +template <typename Function, typename Context> +inline void invoke(Function& function, Context& context) +{ +#if !defined(ASIO_HAS_HANDLER_HOOKS) + Function tmp(function); + tmp(); +#else + using asio::asio_handler_invoke; + asio_handler_invoke(function, asio::detail::addressof(context)); +#endif +} + +template <typename Function, typename Context> +inline void invoke(const Function& function, Context& context) +{ +#if !defined(ASIO_HAS_HANDLER_HOOKS) + Function tmp(function); + tmp(); +#else + using asio::asio_handler_invoke; + asio_handler_invoke(function, asio::detail::addressof(context)); +#endif +} + +} // namespace asio_handler_invoke_helpers + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP diff --git a/asio-1.10.6/include/asio/detail/handler_tracking.hpp b/asio-1.10.6/include/asio/detail/handler_tracking.hpp new file mode 100644 index 0000000..4d1fcb0 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/handler_tracking.hpp @@ -0,0 +1,146 @@ +// +// detail/handler_tracking.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_HANDLER_TRACKING_HPP +#define ASIO_DETAIL_HANDLER_TRACKING_HPP + + +#include "asio/detail/config.hpp" + +#if defined(ASIO_ENABLE_HANDLER_TRACKING) +# include "asio/error_code.hpp" +# include "asio/detail/cstdint.hpp" +# include "asio/detail/static_mutex.hpp" +# include "asio/detail/tss_ptr.hpp" +#endif // defined(ASIO_ENABLE_HANDLER_TRACKING) + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +#if defined(ASIO_ENABLE_HANDLER_TRACKING) + +class handler_tracking +{ +public: + class completion; + + // Base class for objects containing tracked handlers. + class tracked_handler + { + private: + // Only the handler_tracking class will have access to the id. + friend class handler_tracking; + friend class completion; + uint64_t id_; + + protected: + // Constructor initialises with no id. + tracked_handler() : id_(0) {} + + // Prevent deletion through this type. + ~tracked_handler() {} + }; + + // Initialise the tracking system. + ASIO_DECL static void init(); + + // Record the creation of a tracked handler. + ASIO_DECL static void creation(tracked_handler* h, + const char* object_type, void* object, const char* op_name); + + class completion + { + public: + // Constructor records that handler is to be invoked with no arguments. + ASIO_DECL explicit completion(tracked_handler* h); + + // Destructor records only when an exception is thrown from the handler, or + // if the memory is being freed without the handler having been invoked. + ASIO_DECL ~completion(); + + // Records that handler is to be invoked with no arguments. + ASIO_DECL void invocation_begin(); + + // Records that handler is to be invoked with one arguments. + ASIO_DECL void invocation_begin(const asio::error_code& ec); + + // Constructor records that handler is to be invoked with two arguments. + ASIO_DECL void invocation_begin( + const asio::error_code& ec, std::size_t bytes_transferred); + + // Constructor records that handler is to be invoked with two arguments. + ASIO_DECL void invocation_begin( + const asio::error_code& ec, int signal_number); + + // Constructor records that handler is to be invoked with two arguments. + ASIO_DECL void invocation_begin( + const asio::error_code& ec, const char* arg); + + // Record that handler invocation has ended. + ASIO_DECL void invocation_end(); + + private: + friend class handler_tracking; + uint64_t id_; + bool invoked_; + completion* next_; + }; + + // Record an operation that affects pending handlers. + ASIO_DECL static void operation(const char* object_type, + void* object, const char* op_name); + + // Write a line of output. + ASIO_DECL static void write_line(const char* format, ...); + +private: + struct tracking_state; + ASIO_DECL static tracking_state* get_state(); +}; + +# define ASIO_INHERIT_TRACKED_HANDLER : public asio::detail::handler_tracking::tracked_handler + +# define ASIO_ALSO_INHERIT_TRACKED_HANDLER , public asio::detail::handler_tracking::tracked_handler + +# define ASIO_HANDLER_TRACKING_INIT asio::detail::handler_tracking::init() + +# define ASIO_HANDLER_CREATION(args) asio::detail::handler_tracking::creation args + +# define ASIO_HANDLER_COMPLETION(args) asio::detail::handler_tracking::completion tracked_completion args + +# define ASIO_HANDLER_INVOCATION_BEGIN(args) tracked_completion.invocation_begin args + +# define ASIO_HANDLER_INVOCATION_END tracked_completion.invocation_end() + +# define ASIO_HANDLER_OPERATION(args) asio::detail::handler_tracking::operation args + +#else // defined(ASIO_ENABLE_HANDLER_TRACKING) + +# define ASIO_INHERIT_TRACKED_HANDLER +# define ASIO_ALSO_INHERIT_TRACKED_HANDLER +# define ASIO_HANDLER_TRACKING_INIT (void)0 +# define ASIO_HANDLER_CREATION(args) (void)0 +# define ASIO_HANDLER_COMPLETION(args) (void)0 +# define ASIO_HANDLER_INVOCATION_BEGIN(args) (void)0 +# define ASIO_HANDLER_INVOCATION_END (void)0 +# define ASIO_HANDLER_OPERATION(args) (void)0 + +#endif // defined(ASIO_ENABLE_HANDLER_TRACKING) + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +# include "asio/detail/impl/handler_tracking.ipp" + +#endif // ASIO_DETAIL_HANDLER_TRACKING_HPP diff --git a/asio-1.10.6/include/asio/detail/handler_type_requirements.hpp b/asio-1.10.6/include/asio/detail/handler_type_requirements.hpp new file mode 100644 index 0000000..567a6f4 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/handler_type_requirements.hpp @@ -0,0 +1,168 @@ +// +// detail/handler_type_requirements.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_HPP +#define ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_HPP + + +#include "asio/detail/config.hpp" + +// Older versions of gcc have difficulty compiling the sizeof expressions where +// we test the handler type requirements. We'll disable checking of handler type +// requirements for those compilers, but otherwise enable it by default. +#if !defined(ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) +# if !defined(__GNUC__) || (__GNUC__ >= 4) +# define ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS 1 +# endif // !defined(__GNUC__) || (__GNUC__ >= 4) +#endif // !defined(ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) + +// With C++0x we can use a combination of enhanced SFINAE and static_assert to +// generate better template error messages. As this technique is not yet widely +// portable, we'll only enable it for tested compilers. +#if !defined(ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if __has_feature(__cxx_static_assert__) +# define ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 +# endif // __has_feature(cxx_static_assert) +#endif // !defined(ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) + +#if defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) +# include "asio/handler_type.hpp" +#endif // defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) + +// Newer gcc needs special treatment to suppress unused typedef warnings. +#if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) +# define ASIO_UNUSED_TYPEDEF __attribute__((__unused__)) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) +#endif // defined(__GNUC__) +#if !defined(ASIO_UNUSED_TYPEDEF) +# define ASIO_UNUSED_TYPEDEF +#endif // !defined(ASIO_UNUSED_TYPEDEF) + +namespace asio { +namespace detail { + +#if defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) + +# if defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) + +template <typename Handler> +auto zero_arg_handler_test(Handler h, void*) + -> decltype( + sizeof(Handler(static_cast<const Handler&>(h))), + ((h)()), + char(0)); + +template <typename Handler> +char (&zero_arg_handler_test(Handler, ...))[2]; + +template <typename Handler, typename Arg1> +auto one_arg_handler_test(Handler h, Arg1* a1) + -> decltype( + sizeof(Handler(static_cast<const Handler&>(h))), + ((h)(*a1)), + char(0)); + +template <typename Handler> +char (&one_arg_handler_test(Handler h, ...))[2]; + +template <typename Handler, typename Arg1, typename Arg2> +auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2) + -> decltype( + sizeof(Handler(static_cast<const Handler&>(h))), + ((h)(*a1, *a2)), + char(0)); + +template <typename Handler> +char (&two_arg_handler_test(Handler, ...))[2]; + +# define ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) static_assert(expr, msg); + +# else // defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) + +# define ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) + +# endif // defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) + +template <typename T> T& lvref(); +template <typename T> T& lvref(T); +template <typename T> const T& clvref(); +template <typename T> const T& clvref(T); +template <typename T> char argbyv(T); + +template <int> +struct handler_type_requirements +{ +}; + +#define ASIO_COMPLETION_HANDLER_CHECK( handler_type, handler) typedef ASIO_HANDLER_TYPE(handler_type, void()) asio_true_handler_type; ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( sizeof(asio::detail::zero_arg_handler_test( asio::detail::clvref< asio_true_handler_type>(), 0)) == 1, "CompletionHandler type requirements not met") typedef asio::detail::handler_type_requirements< sizeof( asio::detail::argbyv( asio::detail::clvref< asio_true_handler_type>())) + sizeof( asio::detail::lvref< asio_true_handler_type>()(), char(0))> ASIO_UNUSED_TYPEDEF + +#define ASIO_READ_HANDLER_CHECK( handler_type, handler) typedef ASIO_HANDLER_TYPE(handler_type, void(asio::error_code, std::size_t)) asio_true_handler_type; ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( sizeof(asio::detail::two_arg_handler_test( asio::detail::clvref< asio_true_handler_type>(), static_cast<const asio::error_code*>(0), static_cast<const std::size_t*>(0))) == 1, "ReadHandler type requirements not met") typedef asio::detail::handler_type_requirements< sizeof( asio::detail::argbyv( asio::detail::clvref< asio_true_handler_type>())) + sizeof( asio::detail::lvref< asio_true_handler_type>()( asio::detail::lvref<const asio::error_code>(), asio::detail::lvref<const std::size_t>()), char(0))> ASIO_UNUSED_TYPEDEF + + +#define ASIO_WRITE_HANDLER_CHECK( handler_type, handler) typedef ASIO_HANDLER_TYPE(handler_type, void(asio::error_code, std::size_t)) asio_true_handler_type; ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( sizeof(asio::detail::two_arg_handler_test( asio::detail::clvref< asio_true_handler_type>(), static_cast<const asio::error_code*>(0), static_cast<const std::size_t*>(0))) == 1, "WriteHandler type requirements not met") typedef asio::detail::handler_type_requirements< sizeof( asio::detail::argbyv( asio::detail::clvref< asio_true_handler_type>())) + sizeof( asio::detail::lvref< asio_true_handler_type>()( asio::detail::lvref<const asio::error_code>(), asio::detail::lvref<const std::size_t>()), char(0))> ASIO_UNUSED_TYPEDEF + +#define ASIO_ACCEPT_HANDLER_CHECK( handler_type, handler) typedef ASIO_HANDLER_TYPE(handler_type, void(asio::error_code)) asio_true_handler_type; ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( sizeof(asio::detail::one_arg_handler_test( asio::detail::clvref< asio_true_handler_type>(), static_cast<const asio::error_code*>(0))) == 1, "AcceptHandler type requirements not met") typedef asio::detail::handler_type_requirements< sizeof( asio::detail::argbyv( asio::detail::clvref< asio_true_handler_type>())) + sizeof( asio::detail::lvref< asio_true_handler_type>()( asio::detail::lvref<const asio::error_code>()), char(0))> ASIO_UNUSED_TYPEDEF + +#define ASIO_CONNECT_HANDLER_CHECK( handler_type, handler) typedef ASIO_HANDLER_TYPE(handler_type, void(asio::error_code)) asio_true_handler_type; ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( sizeof(asio::detail::one_arg_handler_test( asio::detail::clvref< asio_true_handler_type>(), static_cast<const asio::error_code*>(0))) == 1, "ConnectHandler type requirements not met") typedef asio::detail::handler_type_requirements< sizeof( asio::detail::argbyv( asio::detail::clvref< asio_true_handler_type>())) + sizeof( asio::detail::lvref< asio_true_handler_type>()( asio::detail::lvref<const asio::error_code>()), char(0))> ASIO_UNUSED_TYPEDEF + +#define ASIO_COMPOSED_CONNECT_HANDLER_CHECK( handler_type, handler, iter_type) typedef ASIO_HANDLER_TYPE(handler_type, void(asio::error_code, iter_type)) asio_true_handler_type; ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( sizeof(asio::detail::two_arg_handler_test( asio::detail::clvref< asio_true_handler_type>(), static_cast<const asio::error_code*>(0), static_cast<const iter_type*>(0))) == 1, "ComposedConnectHandler type requirements not met") typedef asio::detail::handler_type_requirements< sizeof( asio::detail::argbyv( asio::detail::clvref< asio_true_handler_type>())) + sizeof( asio::detail::lvref< asio_true_handler_type>()( asio::detail::lvref<const asio::error_code>(), asio::detail::lvref<const iter_type>()), char(0))> ASIO_UNUSED_TYPEDEF + +#define ASIO_RESOLVE_HANDLER_CHECK( handler_type, handler, iter_type) typedef ASIO_HANDLER_TYPE(handler_type, void(asio::error_code, iter_type)) asio_true_handler_type; ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( sizeof(asio::detail::two_arg_handler_test( asio::detail::clvref< asio_true_handler_type>(), static_cast<const asio::error_code*>(0), static_cast<const iter_type*>(0))) == 1, "ResolveHandler type requirements not met") typedef asio::detail::handler_type_requirements< sizeof( asio::detail::argbyv( asio::detail::clvref< asio_true_handler_type>())) + sizeof( asio::detail::lvref< asio_true_handler_type>()( asio::detail::lvref<const asio::error_code>(), asio::detail::lvref<const iter_type>()), char(0))> ASIO_UNUSED_TYPEDEF + +#define ASIO_WAIT_HANDLER_CHECK( handler_type, handler) typedef ASIO_HANDLER_TYPE(handler_type, void(asio::error_code)) asio_true_handler_type; ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( sizeof(asio::detail::one_arg_handler_test( asio::detail::clvref< asio_true_handler_type>(), static_cast<const asio::error_code*>(0))) == 1, "WaitHandler type requirements not met") typedef asio::detail::handler_type_requirements< sizeof( asio::detail::argbyv( asio::detail::clvref< asio_true_handler_type>())) + sizeof( asio::detail::lvref< asio_true_handler_type>()( asio::detail::lvref<const asio::error_code>()), char(0))> ASIO_UNUSED_TYPEDEF + +#define ASIO_SIGNAL_HANDLER_CHECK( handler_type, handler) typedef ASIO_HANDLER_TYPE(handler_type, void(asio::error_code, int)) asio_true_handler_type; ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( sizeof(asio::detail::two_arg_handler_test( asio::detail::clvref< asio_true_handler_type>(), static_cast<const asio::error_code*>(0), static_cast<const int*>(0))) == 1, "SignalHandler type requirements not met") typedef asio::detail::handler_type_requirements< sizeof( asio::detail::argbyv( asio::detail::clvref< asio_true_handler_type>())) + sizeof( asio::detail::lvref< asio_true_handler_type>()( asio::detail::lvref<const asio::error_code>(), asio::detail::lvref<const int>()), char(0))> ASIO_UNUSED_TYPEDEF + +#define ASIO_HANDSHAKE_HANDLER_CHECK( handler_type, handler) typedef ASIO_HANDLER_TYPE(handler_type, void(asio::error_code)) asio_true_handler_type; ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( sizeof(asio::detail::one_arg_handler_test( asio::detail::clvref< asio_true_handler_type>(), static_cast<const asio::error_code*>(0))) == 1, "HandshakeHandler type requirements not met") typedef asio::detail::handler_type_requirements< sizeof( asio::detail::argbyv( asio::detail::clvref< asio_true_handler_type>())) + sizeof( asio::detail::lvref< asio_true_handler_type>()( asio::detail::lvref<const asio::error_code>()), char(0))> ASIO_UNUSED_TYPEDEF + +#define ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( handler_type, handler) typedef ASIO_HANDLER_TYPE(handler_type, void(asio::error_code, std::size_t)) asio_true_handler_type; ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( sizeof(asio::detail::two_arg_handler_test( asio::detail::clvref< asio_true_handler_type>(), static_cast<const asio::error_code*>(0), static_cast<const std::size_t*>(0))) == 1, "BufferedHandshakeHandler type requirements not met") typedef asio::detail::handler_type_requirements< sizeof( asio::detail::argbyv( asio::detail::clvref< asio_true_handler_type>())) + sizeof( asio::detail::lvref< asio_true_handler_type>()( asio::detail::lvref<const asio::error_code>(), asio::detail::lvref<const std::size_t>()), char(0))> ASIO_UNUSED_TYPEDEF + +#define ASIO_SHUTDOWN_HANDLER_CHECK( handler_type, handler) typedef ASIO_HANDLER_TYPE(handler_type, void(asio::error_code)) asio_true_handler_type; ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( sizeof(asio::detail::one_arg_handler_test( asio::detail::clvref< asio_true_handler_type>(), static_cast<const asio::error_code*>(0))) == 1, "ShutdownHandler type requirements not met") typedef asio::detail::handler_type_requirements< sizeof( asio::detail::argbyv( asio::detail::clvref< asio_true_handler_type>())) + sizeof( asio::detail::lvref< asio_true_handler_type>()( asio::detail::lvref<const asio::error_code>()), char(0))> ASIO_UNUSED_TYPEDEF + +#else // !defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) + +#define ASIO_COMPLETION_HANDLER_CHECK( handler_type, handler) typedef int ASIO_UNUSED_TYPEDEF + +#define ASIO_READ_HANDLER_CHECK( handler_type, handler) typedef int ASIO_UNUSED_TYPEDEF + +#define ASIO_WRITE_HANDLER_CHECK( handler_type, handler) typedef int ASIO_UNUSED_TYPEDEF + +#define ASIO_ACCEPT_HANDLER_CHECK( handler_type, handler) typedef int ASIO_UNUSED_TYPEDEF + +#define ASIO_CONNECT_HANDLER_CHECK( handler_type, handler) typedef int ASIO_UNUSED_TYPEDEF + +#define ASIO_COMPOSED_CONNECT_HANDLER_CHECK( handler_type, handler, iter_type) typedef int ASIO_UNUSED_TYPEDEF + +#define ASIO_RESOLVE_HANDLER_CHECK( handler_type, handler, iter_type) typedef int ASIO_UNUSED_TYPEDEF + +#define ASIO_WAIT_HANDLER_CHECK( handler_type, handler) typedef int ASIO_UNUSED_TYPEDEF + +#define ASIO_SIGNAL_HANDLER_CHECK( handler_type, handler) typedef int ASIO_UNUSED_TYPEDEF + +#define ASIO_HANDSHAKE_HANDLER_CHECK( handler_type, handler) typedef int ASIO_UNUSED_TYPEDEF + +#define ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( handler_type, handler) typedef int ASIO_UNUSED_TYPEDEF + +#define ASIO_SHUTDOWN_HANDLER_CHECK( handler_type, handler) typedef int ASIO_UNUSED_TYPEDEF + +#endif // !defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) + +} // namespace detail +} // namespace asio + +#endif // ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_HPP diff --git a/asio-1.10.6/include/asio/detail/hash_map.hpp b/asio-1.10.6/include/asio/detail/hash_map.hpp new file mode 100644 index 0000000..0a99941 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/hash_map.hpp @@ -0,0 +1,319 @@ +// +// detail/hash_map.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_HASH_MAP_HPP +#define ASIO_DETAIL_HASH_MAP_HPP + + +#include "asio/detail/config.hpp" +#include <list> +#include <utility> +#include "asio/detail/assert.hpp" +#include "asio/detail/noncopyable.hpp" + + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +inline std::size_t calculate_hash_value(int i) +{ + return static_cast<std::size_t>(i); +} + +inline std::size_t calculate_hash_value(void* p) +{ + return reinterpret_cast<std::size_t>(p) + + (reinterpret_cast<std::size_t>(p) >> 3); +} + + +// Note: assumes K and V are POD types. +template <typename K, typename V> +class hash_map + : private noncopyable +{ +public: + // The type of a value in the map. + typedef std::pair<K, V> value_type; + + // The type of a non-const iterator over the hash map. + typedef typename std::list<value_type>::iterator iterator; + + // The type of a const iterator over the hash map. + typedef typename std::list<value_type>::const_iterator const_iterator; + + // Constructor. + hash_map() + : size_(0), + buckets_(0), + num_buckets_(0) + { + } + + // Destructor. + ~hash_map() + { + delete[] buckets_; + } + + // Get an iterator for the beginning of the map. + iterator begin() + { + return values_.begin(); + } + + // Get an iterator for the beginning of the map. + const_iterator begin() const + { + return values_.begin(); + } + + // Get an iterator for the end of the map. + iterator end() + { + return values_.end(); + } + + // Get an iterator for the end of the map. + const_iterator end() const + { + return values_.end(); + } + + // Check whether the map is empty. + bool empty() const + { + return values_.empty(); + } + + // Find an entry in the map. + iterator find(const K& k) + { + if (num_buckets_) + { + size_t bucket = calculate_hash_value(k) % num_buckets_; + iterator it = buckets_[bucket].first; + if (it == values_.end()) + return values_.end(); + iterator end_it = buckets_[bucket].last; + ++end_it; + while (it != end_it) + { + if (it->first == k) + return it; + ++it; + } + } + return values_.end(); + } + + // Find an entry in the map. + const_iterator find(const K& k) const + { + if (num_buckets_) + { + size_t bucket = calculate_hash_value(k) % num_buckets_; + const_iterator it = buckets_[bucket].first; + if (it == values_.end()) + return it; + const_iterator end_it = buckets_[bucket].last; + ++end_it; + while (it != end_it) + { + if (it->first == k) + return it; + ++it; + } + } + return values_.end(); + } + + // Insert a new entry into the map. + std::pair<iterator, bool> insert(const value_type& v) + { + if (size_ + 1 >= num_buckets_) + rehash(hash_size(size_ + 1)); + size_t bucket = calculate_hash_value(v.first) % num_buckets_; + iterator it = buckets_[bucket].first; + if (it == values_.end()) + { + buckets_[bucket].first = buckets_[bucket].last = + values_insert(values_.end(), v); + ++size_; + return std::pair<iterator, bool>(buckets_[bucket].last, true); + } + iterator end_it = buckets_[bucket].last; + ++end_it; + while (it != end_it) + { + if (it->first == v.first) + return std::pair<iterator, bool>(it, false); + ++it; + } + buckets_[bucket].last = values_insert(end_it, v); + ++size_; + return std::pair<iterator, bool>(buckets_[bucket].last, true); + } + + // Erase an entry from the map. + void erase(iterator it) + { + ASIO_ASSERT(it != values_.end()); + ASIO_ASSERT(num_buckets_ != 0); + + size_t bucket = calculate_hash_value(it->first) % num_buckets_; + bool is_first = (it == buckets_[bucket].first); + bool is_last = (it == buckets_[bucket].last); + if (is_first && is_last) + buckets_[bucket].first = buckets_[bucket].last = values_.end(); + else if (is_first) + ++buckets_[bucket].first; + else if (is_last) + --buckets_[bucket].last; + + values_erase(it); + --size_; + } + + // Erase a key from the map. + void erase(const K& k) + { + iterator it = find(k); + if (it != values_.end()) + erase(it); + } + + // Remove all entries from the map. + void clear() + { + // Clear the values. + values_.clear(); + size_ = 0; + + // Initialise all buckets to empty. + iterator end_it = values_.end(); + for (size_t i = 0; i < num_buckets_; ++i) + buckets_[i].first = buckets_[i].last = end_it; + } + +private: + // Calculate the hash size for the specified number of elements. + static std::size_t hash_size(std::size_t num_elems) + { + static std::size_t sizes[] = + { +#if defined(ASIO_HASH_MAP_BUCKETS) + ASIO_HASH_MAP_BUCKETS +#else // ASIO_HASH_MAP_BUCKETS + 3, 13, 23, 53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593, + 49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469, + 12582917, 25165843 +#endif // ASIO_HASH_MAP_BUCKETS + }; + const std::size_t nth_size = sizeof(sizes) / sizeof(std::size_t) - 1; + for (std::size_t i = 0; i < nth_size; ++i) + if (num_elems < sizes[i]) + return sizes[i]; + return sizes[nth_size]; + } + + // Re-initialise the hash from the values already contained in the list. + void rehash(std::size_t num_buckets) + { + if (num_buckets == num_buckets_) + return; + num_buckets_ = num_buckets; + ASIO_ASSERT(num_buckets_ != 0); + + iterator end_iter = values_.end(); + + // Update number of buckets and initialise all buckets to empty. + bucket_type* tmp = new bucket_type[num_buckets_]; + delete[] buckets_; + buckets_ = tmp; + for (std::size_t i = 0; i < num_buckets_; ++i) + buckets_[i].first = buckets_[i].last = end_iter; + + // Put all values back into the hash. + iterator iter = values_.begin(); + while (iter != end_iter) + { + std::size_t bucket = calculate_hash_value(iter->first) % num_buckets_; + if (buckets_[bucket].last == end_iter) + { + buckets_[bucket].first = buckets_[bucket].last = iter++; + } + else if (++buckets_[bucket].last == iter) + { + ++iter; + } + else + { + values_.splice(buckets_[bucket].last, values_, iter++); + --buckets_[bucket].last; + } + } + } + + // Insert an element into the values list by splicing from the spares list, + // if a spare is available, and otherwise by inserting a new element. + iterator values_insert(iterator it, const value_type& v) + { + if (spares_.empty()) + { + return values_.insert(it, v); + } + else + { + spares_.front() = v; + values_.splice(it, spares_, spares_.begin()); + return --it; + } + } + + // Erase an element from the values list by splicing it to the spares list. + void values_erase(iterator it) + { + *it = value_type(); + spares_.splice(spares_.begin(), values_, it); + } + + // The number of elements in the hash. + std::size_t size_; + + // The list of all values in the hash map. + std::list<value_type> values_; + + // The list of spare nodes waiting to be recycled. Assumes that POD types only + // are stored in the hash map. + std::list<value_type> spares_; + + // The type for a bucket in the hash table. + struct bucket_type + { + iterator first; + iterator last; + }; + + // The buckets in the hash. + bucket_type* buckets_; + + // The number of buckets in the hash. + std::size_t num_buckets_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_HASH_MAP_HPP diff --git a/asio-1.10.6/include/asio/detail/impl/buffer_sequence_adapter.ipp b/asio-1.10.6/include/asio/detail/impl/buffer_sequence_adapter.ipp new file mode 100644 index 0000000..41ff7f3 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/impl/buffer_sequence_adapter.ipp @@ -0,0 +1,18 @@ +// +// detail/impl/buffer_sequence_adapter.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IMPL_BUFFER_SEQUENCE_ADAPTER_IPP +#define ASIO_DETAIL_IMPL_BUFFER_SEQUENCE_ADAPTER_IPP + + +#include "asio/detail/config.hpp" + + +#endif // ASIO_DETAIL_IMPL_BUFFER_SEQUENCE_ADAPTER_IPP diff --git a/asio-1.10.6/include/asio/detail/impl/handler_tracking.ipp b/asio-1.10.6/include/asio/detail/impl/handler_tracking.ipp new file mode 100644 index 0000000..7cb5ca6 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/impl/handler_tracking.ipp @@ -0,0 +1,239 @@ +// +// detail/impl/handler_tracking.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP +#define ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP + + +#include "asio/detail/config.hpp" + +#if defined(ASIO_ENABLE_HANDLER_TRACKING) + +#include <cstdarg> +#include <cstdio> +#include "asio/detail/handler_tracking.hpp" + +# include <chrono> +# include "asio/detail/chrono_time_traits.hpp" +# include "asio/wait_traits.hpp" + +# include <unistd.h> + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +struct handler_tracking_timestamp +{ + uint64_t seconds; + uint64_t microseconds; + + handler_tracking_timestamp() + { + typedef chrono_time_traits<std::chrono::system_clock, + asio::wait_traits<std::chrono::system_clock> > traits_helper; + traits_helper::posix_time_duration now( + std::chrono::system_clock::now().time_since_epoch()); + seconds = static_cast<uint64_t>(now.total_seconds()); + microseconds = static_cast<uint64_t>(now.total_microseconds() % 1000000); + } +}; + +struct handler_tracking::tracking_state +{ + static_mutex mutex_; + uint64_t next_id_; + tss_ptr<completion>* current_completion_; +}; + +handler_tracking::tracking_state* handler_tracking::get_state() +{ + static tracking_state state = { ASIO_STATIC_MUTEX_INIT, 1, 0 }; + return &state; +} + +void handler_tracking::init() +{ + static tracking_state* state = get_state(); + + state->mutex_.init(); + + static_mutex::scoped_lock lock(state->mutex_); + if (state->current_completion_ == 0) + state->current_completion_ = new tss_ptr<completion>; +} + +void handler_tracking::creation(handler_tracking::tracked_handler* h, + const char* object_type, void* object, const char* op_name) +{ + static tracking_state* state = get_state(); + + static_mutex::scoped_lock lock(state->mutex_); + h->id_ = state->next_id_++; + lock.unlock(); + + handler_tracking_timestamp timestamp; + + uint64_t current_id = 0; + if (completion* current_completion = *state->current_completion_) + current_id = current_completion->id_; + + write_line( + "@asio|%llu.%06llu|%llu*%llu|%.20s@%p.%.50s\n", + timestamp.seconds, timestamp.microseconds, + current_id, h->id_, object_type, object, op_name); +} + +handler_tracking::completion::completion(handler_tracking::tracked_handler* h) + : id_(h->id_), + invoked_(false), + next_(*get_state()->current_completion_) +{ + *get_state()->current_completion_ = this; +} + +handler_tracking::completion::~completion() +{ + if (id_) + { + handler_tracking_timestamp timestamp; + + write_line( + "@asio|%llu.%06llu|%c%llu|\n", + timestamp.seconds, timestamp.microseconds, + invoked_ ? '!' : '~', id_); + } + + *get_state()->current_completion_ = next_; +} + +void handler_tracking::completion::invocation_begin() +{ + handler_tracking_timestamp timestamp; + + write_line( + "@asio|%llu.%06llu|>%llu|\n", + timestamp.seconds, timestamp.microseconds, id_); + + invoked_ = true; +} + +void handler_tracking::completion::invocation_begin( + const asio::error_code& ec) +{ + handler_tracking_timestamp timestamp; + + write_line( + "@asio|%llu.%06llu|>%llu|ec=%.20s:%d\n", + timestamp.seconds, timestamp.microseconds, + id_, ec.category().name(), ec.value()); + + invoked_ = true; +} + +void handler_tracking::completion::invocation_begin( + const asio::error_code& ec, std::size_t bytes_transferred) +{ + handler_tracking_timestamp timestamp; + + write_line( + "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,bytes_transferred=%llu\n", + timestamp.seconds, timestamp.microseconds, + id_, ec.category().name(), ec.value(), + static_cast<uint64_t>(bytes_transferred)); + + invoked_ = true; +} + +void handler_tracking::completion::invocation_begin( + const asio::error_code& ec, int signal_number) +{ + handler_tracking_timestamp timestamp; + + write_line( + "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,signal_number=%d\n", + timestamp.seconds, timestamp.microseconds, + id_, ec.category().name(), ec.value(), signal_number); + + invoked_ = true; +} + +void handler_tracking::completion::invocation_begin( + const asio::error_code& ec, const char* arg) +{ + handler_tracking_timestamp timestamp; + + write_line( + "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,%.50s\n", + timestamp.seconds, timestamp.microseconds, + id_, ec.category().name(), ec.value(), arg); + + invoked_ = true; +} + +void handler_tracking::completion::invocation_end() +{ + if (id_) + { + handler_tracking_timestamp timestamp; + + write_line( + "@asio|%llu.%06llu|<%llu|\n", + timestamp.seconds, timestamp.microseconds, id_); + + id_ = 0; + } +} + +void handler_tracking::operation(const char* object_type, + void* object, const char* op_name) +{ + static tracking_state* state = get_state(); + + handler_tracking_timestamp timestamp; + + unsigned long long current_id = 0; + if (completion* current_completion = *state->current_completion_) + current_id = current_completion->id_; + + write_line( + "@asio|%llu.%06llu|%llu|%.20s@%p.%.50s\n", + timestamp.seconds, timestamp.microseconds, + current_id, object_type, object, op_name); +} + +void handler_tracking::write_line(const char* format, ...) +{ + using namespace std; // For sprintf (or equivalent). + + va_list args; + va_start(args, format); + + char line[256] = ""; +#if defined(ASIO_HAS_SECURE_RTL) + int length = vsprintf_s(line, sizeof(line), format, args); +#else // defined(ASIO_HAS_SECURE_RTL) + int length = vsprintf(line, format, args); +#endif // defined(ASIO_HAS_SECURE_RTL) + + va_end(args); + + ::write(STDERR_FILENO, line, length); +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_ENABLE_HANDLER_TRACKING) + +#endif // ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP diff --git a/asio-1.10.6/include/asio/detail/impl/pipe_select_interrupter.ipp b/asio-1.10.6/include/asio/detail/impl/pipe_select_interrupter.ipp new file mode 100644 index 0000000..224de24 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/impl/pipe_select_interrupter.ipp @@ -0,0 +1,111 @@ +// +// detail/impl/pipe_select_interrupter.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IMPL_PIPE_SELECT_INTERRUPTER_IPP +#define ASIO_DETAIL_IMPL_PIPE_SELECT_INTERRUPTER_IPP + + +#include "asio/detail/config.hpp" + + +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> +#include "asio/detail/pipe_select_interrupter.hpp" +#include "asio/detail/socket_types.hpp" +#include "asio/detail/throw_error.hpp" +#include "asio/error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +pipe_select_interrupter::pipe_select_interrupter() +{ + open_descriptors(); +} + +void pipe_select_interrupter::open_descriptors() +{ + int pipe_fds[2]; + if (pipe(pipe_fds) == 0) + { + read_descriptor_ = pipe_fds[0]; + ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK); + write_descriptor_ = pipe_fds[1]; + ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK); + +#if defined(FD_CLOEXEC) + ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC); + ::fcntl(write_descriptor_, F_SETFD, FD_CLOEXEC); +#endif // defined(FD_CLOEXEC) + } + else + { + asio::error_code ec(errno, + asio::error::get_system_category()); + asio::detail::throw_error(ec, "pipe_select_interrupter"); + } +} + +pipe_select_interrupter::~pipe_select_interrupter() +{ + close_descriptors(); +} + +void pipe_select_interrupter::close_descriptors() +{ + if (read_descriptor_ != -1) + ::close(read_descriptor_); + if (write_descriptor_ != -1) + ::close(write_descriptor_); +} + +void pipe_select_interrupter::recreate() +{ + close_descriptors(); + + write_descriptor_ = -1; + read_descriptor_ = -1; + + open_descriptors(); +} + +void pipe_select_interrupter::interrupt() +{ + char byte = 0; + signed_size_type result = ::write(write_descriptor_, &byte, 1); + (void)result; +} + +bool pipe_select_interrupter::reset() +{ + for (;;) + { + char data[1024]; + signed_size_type bytes_read = ::read(read_descriptor_, data, sizeof(data)); + if (bytes_read < 0 && errno == EINTR) + continue; + bool was_interrupted = (bytes_read > 0); + while (bytes_read == sizeof(data)) + bytes_read = ::read(read_descriptor_, data, sizeof(data)); + return was_interrupted; + } +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + + +#endif // ASIO_DETAIL_IMPL_PIPE_SELECT_INTERRUPTER_IPP diff --git a/asio-1.10.6/include/asio/detail/impl/posix_event.ipp b/asio-1.10.6/include/asio/detail/impl/posix_event.ipp new file mode 100644 index 0000000..4ae2a2a --- /dev/null +++ b/asio-1.10.6/include/asio/detail/impl/posix_event.ipp @@ -0,0 +1,44 @@ +// +// detail/impl/posix_event.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IMPL_POSIX_EVENT_IPP +#define ASIO_DETAIL_IMPL_POSIX_EVENT_IPP + + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_PTHREADS) + +#include "asio/detail/posix_event.hpp" +#include "asio/detail/throw_error.hpp" +#include "asio/error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +posix_event::posix_event() + : state_(0) +{ + int error = ::pthread_cond_init(&cond_, 0); + asio::error_code ec(error, + asio::error::get_system_category()); + asio::detail::throw_error(ec, "event"); +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_PTHREADS) + +#endif // ASIO_DETAIL_IMPL_POSIX_EVENT_IPP diff --git a/asio-1.10.6/include/asio/detail/impl/posix_mutex.ipp b/asio-1.10.6/include/asio/detail/impl/posix_mutex.ipp new file mode 100644 index 0000000..ffbbe1c --- /dev/null +++ b/asio-1.10.6/include/asio/detail/impl/posix_mutex.ipp @@ -0,0 +1,43 @@ +// +// detail/impl/posix_mutex.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IMPL_POSIX_MUTEX_IPP +#define ASIO_DETAIL_IMPL_POSIX_MUTEX_IPP + + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_PTHREADS) + +#include "asio/detail/posix_mutex.hpp" +#include "asio/detail/throw_error.hpp" +#include "asio/error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +posix_mutex::posix_mutex() +{ + int error = ::pthread_mutex_init(&mutex_, 0); + asio::error_code ec(error, + asio::error::get_system_category()); + asio::detail::throw_error(ec, "mutex"); +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_PTHREADS) + +#endif // ASIO_DETAIL_IMPL_POSIX_MUTEX_IPP diff --git a/asio-1.10.6/include/asio/detail/impl/posix_thread.ipp b/asio-1.10.6/include/asio/detail/impl/posix_thread.ipp new file mode 100644 index 0000000..fb945c7 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/impl/posix_thread.ipp @@ -0,0 +1,71 @@ +// +// detail/impl/posix_thread.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IMPL_POSIX_THREAD_IPP +#define ASIO_DETAIL_IMPL_POSIX_THREAD_IPP + + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_PTHREADS) + +#include "asio/detail/posix_thread.hpp" +#include "asio/detail/throw_error.hpp" +#include "asio/error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +posix_thread::~posix_thread() +{ + if (!joined_) + ::pthread_detach(thread_); +} + +void posix_thread::join() +{ + if (!joined_) + { + ::pthread_join(thread_, 0); + joined_ = true; + } +} + +void posix_thread::start_thread(func_base* arg) +{ + int error = ::pthread_create(&thread_, 0, + asio_detail_posix_thread_function, arg); + if (error != 0) + { + delete arg; + asio::error_code ec(error, + asio::error::get_system_category()); + asio::detail::throw_error(ec, "thread"); + } +} + +void* asio_detail_posix_thread_function(void* arg) +{ + posix_thread::auto_func_base_ptr func = { + static_cast<posix_thread::func_base*>(arg) }; + func.ptr->run(); + return 0; +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_PTHREADS) + +#endif // ASIO_DETAIL_IMPL_POSIX_THREAD_IPP diff --git a/asio-1.10.6/include/asio/detail/impl/posix_tss_ptr.ipp b/asio-1.10.6/include/asio/detail/impl/posix_tss_ptr.ipp new file mode 100644 index 0000000..37e88b9 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/impl/posix_tss_ptr.ipp @@ -0,0 +1,43 @@ +// +// detail/impl/posix_tss_ptr.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IMPL_POSIX_TSS_PTR_IPP +#define ASIO_DETAIL_IMPL_POSIX_TSS_PTR_IPP + + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_PTHREADS) + +#include "asio/detail/posix_tss_ptr.hpp" +#include "asio/detail/throw_error.hpp" +#include "asio/error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +void posix_tss_ptr_create(pthread_key_t& key) +{ + int error = ::pthread_key_create(&key, 0); + asio::error_code ec(error, + asio::error::get_system_category()); + asio::detail::throw_error(ec, "tss"); +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_PTHREADS) + +#endif // ASIO_DETAIL_IMPL_POSIX_TSS_PTR_IPP diff --git a/asio-1.10.6/include/asio/detail/impl/reactive_socket_service_base.ipp b/asio-1.10.6/include/asio/detail/impl/reactive_socket_service_base.ipp new file mode 100644 index 0000000..bc4088a --- /dev/null +++ b/asio-1.10.6/include/asio/detail/impl/reactive_socket_service_base.ipp @@ -0,0 +1,261 @@ +// +// detail/reactive_socket_service_base.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_IPP +#define ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_IPP + + +#include "asio/detail/config.hpp" + + +#include "asio/detail/reactive_socket_service_base.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +reactive_socket_service_base::reactive_socket_service_base( + asio::io_service& io_service) + : reactor_(use_service<reactor>(io_service)) +{ + reactor_.init_task(); +} + +void reactive_socket_service_base::shutdown_service() +{ +} + +void reactive_socket_service_base::construct( + reactive_socket_service_base::base_implementation_type& impl) +{ + impl.socket_ = invalid_socket; + impl.state_ = 0; +} + +void reactive_socket_service_base::base_move_construct( + reactive_socket_service_base::base_implementation_type& impl, + reactive_socket_service_base::base_implementation_type& other_impl) +{ + impl.socket_ = other_impl.socket_; + other_impl.socket_ = invalid_socket; + + impl.state_ = other_impl.state_; + other_impl.state_ = 0; + + reactor_.move_descriptor(impl.socket_, + impl.reactor_data_, other_impl.reactor_data_); +} + +void reactive_socket_service_base::base_move_assign( + reactive_socket_service_base::base_implementation_type& impl, + reactive_socket_service_base& other_service, + reactive_socket_service_base::base_implementation_type& other_impl) +{ + destroy(impl); + + impl.socket_ = other_impl.socket_; + other_impl.socket_ = invalid_socket; + + impl.state_ = other_impl.state_; + other_impl.state_ = 0; + + other_service.reactor_.move_descriptor(impl.socket_, + impl.reactor_data_, other_impl.reactor_data_); +} + +void reactive_socket_service_base::destroy( + reactive_socket_service_base::base_implementation_type& impl) +{ + if (impl.socket_ != invalid_socket) + { + ASIO_HANDLER_OPERATION(("socket", &impl, "close")); + + reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, + (impl.state_ & socket_ops::possible_dup) == 0); + + asio::error_code ignored_ec; + socket_ops::close(impl.socket_, impl.state_, true, ignored_ec); + } +} + +asio::error_code reactive_socket_service_base::close( + reactive_socket_service_base::base_implementation_type& impl, + asio::error_code& ec) +{ + if (is_open(impl)) + { + ASIO_HANDLER_OPERATION(("socket", &impl, "close")); + + reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, + (impl.state_ & socket_ops::possible_dup) == 0); + } + + socket_ops::close(impl.socket_, impl.state_, false, ec); + + // The descriptor is closed by the OS even if close() returns an error. + // + // (Actually, POSIX says the state of the descriptor is unspecified. On + // Linux the descriptor is apparently closed anyway; e.g. see + // http://lkml.org/lkml/2005/9/10/129 + // We'll just have to assume that other OSes follow the same behaviour. The + // known exception is when Windows's closesocket() function fails with + // WSAEWOULDBLOCK, but this case is handled inside socket_ops::close(). + construct(impl); + + return ec; +} + +asio::error_code reactive_socket_service_base::cancel( + reactive_socket_service_base::base_implementation_type& impl, + asio::error_code& ec) +{ + if (!is_open(impl)) + { + ec = asio::error::bad_descriptor; + return ec; + } + + ASIO_HANDLER_OPERATION(("socket", &impl, "cancel")); + + reactor_.cancel_ops(impl.socket_, impl.reactor_data_); + ec = asio::error_code(); + return ec; +} + +asio::error_code reactive_socket_service_base::do_open( + reactive_socket_service_base::base_implementation_type& impl, + int af, int type, int protocol, asio::error_code& ec) +{ + if (is_open(impl)) + { + ec = asio::error::already_open; + return ec; + } + + socket_holder sock(socket_ops::socket(af, type, protocol, ec)); + if (sock.get() == invalid_socket) + return ec; + + if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_)) + { + ec = asio::error_code(err, + asio::error::get_system_category()); + return ec; + } + + impl.socket_ = sock.release(); + switch (type) + { + case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break; + case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break; + default: impl.state_ = 0; break; + } + ec = asio::error_code(); + return ec; +} + +asio::error_code reactive_socket_service_base::do_assign( + reactive_socket_service_base::base_implementation_type& impl, int type, + const reactive_socket_service_base::native_handle_type& native_socket, + asio::error_code& ec) +{ + if (is_open(impl)) + { + ec = asio::error::already_open; + return ec; + } + + if (int err = reactor_.register_descriptor( + native_socket, impl.reactor_data_)) + { + ec = asio::error_code(err, + asio::error::get_system_category()); + return ec; + } + + impl.socket_ = native_socket; + switch (type) + { + case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break; + case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break; + default: impl.state_ = 0; break; + } + impl.state_ |= socket_ops::possible_dup; + ec = asio::error_code(); + return ec; +} + +void reactive_socket_service_base::start_op( + reactive_socket_service_base::base_implementation_type& impl, + int op_type, reactor_op* op, bool is_continuation, + bool is_non_blocking, bool noop) +{ + if (!noop) + { + if ((impl.state_ & socket_ops::non_blocking) + || socket_ops::set_internal_non_blocking( + impl.socket_, impl.state_, true, op->ec_)) + { + reactor_.start_op(op_type, impl.socket_, + impl.reactor_data_, op, is_continuation, is_non_blocking); + return; + } + } + + reactor_.post_immediate_completion(op, is_continuation); +} + +void reactive_socket_service_base::start_accept_op( + reactive_socket_service_base::base_implementation_type& impl, + reactor_op* op, bool is_continuation, bool peer_is_open) +{ + if (!peer_is_open) + start_op(impl, reactor::read_op, op, true, is_continuation, false); + else + { + op->ec_ = asio::error::already_open; + reactor_.post_immediate_completion(op, is_continuation); + } +} + +void reactive_socket_service_base::start_connect_op( + reactive_socket_service_base::base_implementation_type& impl, + reactor_op* op, bool is_continuation, + const socket_addr_type* addr, size_t addrlen) +{ + if ((impl.state_ & socket_ops::non_blocking) + || socket_ops::set_internal_non_blocking( + impl.socket_, impl.state_, true, op->ec_)) + { + if (socket_ops::connect(impl.socket_, addr, addrlen, op->ec_) != 0) + { + if (op->ec_ == asio::error::in_progress + || op->ec_ == asio::error::would_block) + { + op->ec_ = asio::error_code(); + reactor_.start_op(reactor::connect_op, impl.socket_, + impl.reactor_data_, op, is_continuation, false); + return; + } + } + } + + reactor_.post_immediate_completion(op, is_continuation); +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + + // && !defined(ASIO_WINDOWS_RUNTIME) + +#endif // ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_IPP diff --git a/asio-1.10.6/include/asio/detail/impl/resolver_service_base.ipp b/asio-1.10.6/include/asio/detail/impl/resolver_service_base.ipp new file mode 100644 index 0000000..2868a08 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/impl/resolver_service_base.ipp @@ -0,0 +1,127 @@ +// +// detail/impl/resolver_service_base.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IMPL_RESOLVER_SERVICE_BASE_IPP +#define ASIO_DETAIL_IMPL_RESOLVER_SERVICE_BASE_IPP + + +#include "asio/detail/config.hpp" +#include "asio/detail/resolver_service_base.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class resolver_service_base::work_io_service_runner +{ +public: + work_io_service_runner(asio::io_service& io_service) + : io_service_(io_service) {} + void operator()() { io_service_.run(); } +private: + asio::io_service& io_service_; +}; + +resolver_service_base::resolver_service_base( + asio::io_service& io_service) + : io_service_impl_(asio::use_service<io_service_impl>(io_service)), + work_io_service_(new asio::io_service), + work_io_service_impl_(asio::use_service< + io_service_impl>(*work_io_service_)), + work_(new asio::io_service::work(*work_io_service_)), + work_thread_(0) +{ +} + +resolver_service_base::~resolver_service_base() +{ + shutdown_service(); +} + +void resolver_service_base::shutdown_service() +{ + work_.reset(); + if (work_io_service_.get()) + { + work_io_service_->stop(); + if (work_thread_.get()) + { + work_thread_->join(); + work_thread_.reset(); + } + work_io_service_.reset(); + } +} + +void resolver_service_base::fork_service( + asio::io_service::fork_event fork_ev) +{ + if (work_thread_.get()) + { + if (fork_ev == asio::io_service::fork_prepare) + { + work_io_service_->stop(); + work_thread_->join(); + } + else + { + work_io_service_->reset(); + work_thread_.reset(new asio::detail::thread( + work_io_service_runner(*work_io_service_))); + } + } +} + +void resolver_service_base::construct( + resolver_service_base::implementation_type& impl) +{ + impl.reset(static_cast<void*>(0), socket_ops::noop_deleter()); +} + +void resolver_service_base::destroy( + resolver_service_base::implementation_type& impl) +{ + ASIO_HANDLER_OPERATION(("resolver", &impl, "cancel")); + + impl.reset(); +} + +void resolver_service_base::cancel( + resolver_service_base::implementation_type& impl) +{ + ASIO_HANDLER_OPERATION(("resolver", &impl, "cancel")); + + impl.reset(static_cast<void*>(0), socket_ops::noop_deleter()); +} + +void resolver_service_base::start_resolve_op(operation* op) +{ + start_work_thread(); + io_service_impl_.work_started(); + work_io_service_impl_.post_immediate_completion(op, false); +} + +void resolver_service_base::start_work_thread() +{ + asio::detail::mutex::scoped_lock lock(mutex_); + if (!work_thread_.get()) + { + work_thread_.reset(new asio::detail::thread( + work_io_service_runner(*work_io_service_))); + } +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_IMPL_RESOLVER_SERVICE_BASE_IPP diff --git a/asio-1.10.6/include/asio/detail/impl/select_reactor.hpp b/asio-1.10.6/include/asio/detail/impl/select_reactor.hpp new file mode 100644 index 0000000..06b0acf --- /dev/null +++ b/asio-1.10.6/include/asio/detail/impl/select_reactor.hpp @@ -0,0 +1,80 @@ +// +// detail/impl/select_reactor.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IMPL_SELECT_REACTOR_HPP +#define ASIO_DETAIL_IMPL_SELECT_REACTOR_HPP + + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_IOCP) || (!defined(ASIO_HAS_DEV_POLL) && !defined(ASIO_HAS_EPOLL) && !defined(ASIO_HAS_KQUEUE) && !defined(ASIO_WINDOWS_RUNTIME)) + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename Time_Traits> +void select_reactor::add_timer_queue(timer_queue<Time_Traits>& queue) +{ + do_add_timer_queue(queue); +} + +// Remove a timer queue from the reactor. +template <typename Time_Traits> +void select_reactor::remove_timer_queue(timer_queue<Time_Traits>& queue) +{ + do_remove_timer_queue(queue); +} + +template <typename Time_Traits> +void select_reactor::schedule_timer(timer_queue<Time_Traits>& queue, + const typename Time_Traits::time_type& time, + typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op) +{ + asio::detail::mutex::scoped_lock lock(mutex_); + + if (shutdown_) + { + io_service_.post_immediate_completion(op, false); + return; + } + + bool earliest = queue.enqueue_timer(time, timer, op); + io_service_.work_started(); + if (earliest) + interrupter_.interrupt(); +} + +template <typename Time_Traits> +std::size_t select_reactor::cancel_timer(timer_queue<Time_Traits>& queue, + typename timer_queue<Time_Traits>::per_timer_data& timer, + std::size_t max_cancelled) +{ + asio::detail::mutex::scoped_lock lock(mutex_); + op_queue<operation> ops; + std::size_t n = queue.cancel_timer(timer, ops, max_cancelled); + lock.unlock(); + io_service_.post_deferred_completions(ops); + return n; +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_IOCP) + // || (!defined(ASIO_HAS_DEV_POLL) + // && !defined(ASIO_HAS_EPOLL) + // && !defined(ASIO_HAS_KQUEUE) + // && !defined(ASIO_WINDOWS_RUNTIME)) + +#endif // ASIO_DETAIL_IMPL_SELECT_REACTOR_HPP diff --git a/asio-1.10.6/include/asio/detail/impl/select_reactor.ipp b/asio-1.10.6/include/asio/detail/impl/select_reactor.ipp new file mode 100644 index 0000000..804a31f --- /dev/null +++ b/asio-1.10.6/include/asio/detail/impl/select_reactor.ipp @@ -0,0 +1,246 @@ +// +// detail/impl/select_reactor.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IMPL_SELECT_REACTOR_IPP +#define ASIO_DETAIL_IMPL_SELECT_REACTOR_IPP + + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_IOCP) || (!defined(ASIO_HAS_DEV_POLL) && !defined(ASIO_HAS_EPOLL) && !defined(ASIO_HAS_KQUEUE) && !defined(ASIO_WINDOWS_RUNTIME)) + +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/fd_set_adapter.hpp" +#include "asio/detail/select_reactor.hpp" +#include "asio/detail/signal_blocker.hpp" +#include "asio/detail/socket_ops.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +select_reactor::select_reactor(asio::io_service& io_service) + : asio::detail::service_base<select_reactor>(io_service), + io_service_(use_service<io_service_impl>(io_service)), + mutex_(), + interrupter_(), + shutdown_(false) +{ +} + +select_reactor::~select_reactor() +{ + shutdown_service(); +} + +void select_reactor::shutdown_service() +{ + asio::detail::mutex::scoped_lock lock(mutex_); + shutdown_ = true; + lock.unlock(); + + + op_queue<operation> ops; + + for (int i = 0; i < max_ops; ++i) + op_queue_[i].get_all_operations(ops); + + timer_queues_.get_all_timers(ops); + + io_service_.abandon_operations(ops); +} + +void select_reactor::fork_service(asio::io_service::fork_event fork_ev) +{ + if (fork_ev == asio::io_service::fork_child) + interrupter_.recreate(); +} + +void select_reactor::init_task() +{ + io_service_.init_task(); +} + +int select_reactor::register_descriptor(socket_type, + select_reactor::per_descriptor_data&) +{ + return 0; +} + +int select_reactor::register_internal_descriptor( + int op_type, socket_type descriptor, + select_reactor::per_descriptor_data&, reactor_op* op) +{ + asio::detail::mutex::scoped_lock lock(mutex_); + + op_queue_[op_type].enqueue_operation(descriptor, op); + interrupter_.interrupt(); + + return 0; +} + +void select_reactor::move_descriptor(socket_type, + select_reactor::per_descriptor_data&, + select_reactor::per_descriptor_data&) +{ +} + +void select_reactor::start_op(int op_type, socket_type descriptor, + select_reactor::per_descriptor_data&, reactor_op* op, + bool is_continuation, bool) +{ + asio::detail::mutex::scoped_lock lock(mutex_); + + if (shutdown_) + { + post_immediate_completion(op, is_continuation); + return; + } + + bool first = op_queue_[op_type].enqueue_operation(descriptor, op); + io_service_.work_started(); + if (first) + interrupter_.interrupt(); +} + +void select_reactor::cancel_ops(socket_type descriptor, + select_reactor::per_descriptor_data&) +{ + asio::detail::mutex::scoped_lock lock(mutex_); + cancel_ops_unlocked(descriptor, asio::error::operation_aborted); +} + +void select_reactor::deregister_descriptor(socket_type descriptor, + select_reactor::per_descriptor_data&, bool) +{ + asio::detail::mutex::scoped_lock lock(mutex_); + cancel_ops_unlocked(descriptor, asio::error::operation_aborted); +} + +void select_reactor::deregister_internal_descriptor( + socket_type descriptor, select_reactor::per_descriptor_data&) +{ + asio::detail::mutex::scoped_lock lock(mutex_); + op_queue<operation> ops; + for (int i = 0; i < max_ops; ++i) + op_queue_[i].cancel_operations(descriptor, ops); +} + +void select_reactor::run(bool block, op_queue<operation>& ops) +{ + asio::detail::mutex::scoped_lock lock(mutex_); + + + // Set up the descriptor sets. + for (int i = 0; i < max_select_ops; ++i) + fd_sets_[i].reset(); + fd_sets_[read_op].set(interrupter_.read_descriptor()); + socket_type max_fd = 0; + bool have_work_to_do = !timer_queues_.all_empty(); + for (int i = 0; i < max_select_ops; ++i) + { + have_work_to_do = have_work_to_do || !op_queue_[i].empty(); + fd_sets_[i].set(op_queue_[i], ops); + if (fd_sets_[i].max_descriptor() > max_fd) + max_fd = fd_sets_[i].max_descriptor(); + } + + + // We can return immediately if there's no work to do and the reactor is + // not supposed to block. + if (!block && !have_work_to_do) + return; + + // Determine how long to block while waiting for events. + timeval tv_buf = { 0, 0 }; + timeval* tv = block ? get_timeout(tv_buf) : &tv_buf; + + lock.unlock(); + + // Block on the select call until descriptors become ready. + asio::error_code ec; + int retval = socket_ops::select(static_cast<int>(max_fd + 1), + fd_sets_[read_op], fd_sets_[write_op], fd_sets_[except_op], tv, ec); + + // Reset the interrupter. + if (retval > 0 && fd_sets_[read_op].is_set(interrupter_.read_descriptor())) + { + interrupter_.reset(); + --retval; + } + + lock.lock(); + + // Dispatch all ready operations. + if (retval > 0) + { + + // Exception operations must be processed first to ensure that any + // out-of-band data is read before normal data. + for (int i = max_select_ops - 1; i >= 0; --i) + fd_sets_[i].perform(op_queue_[i], ops); + } + timer_queues_.get_ready_timers(ops); +} + +void select_reactor::interrupt() +{ + interrupter_.interrupt(); +} + + +void select_reactor::do_add_timer_queue(timer_queue_base& queue) +{ + mutex::scoped_lock lock(mutex_); + timer_queues_.insert(&queue); +} + +void select_reactor::do_remove_timer_queue(timer_queue_base& queue) +{ + mutex::scoped_lock lock(mutex_); + timer_queues_.erase(&queue); +} + +timeval* select_reactor::get_timeout(timeval& tv) +{ + // By default we will wait no longer than 5 minutes. This will ensure that + // any changes to the system clock are detected after no longer than this. + long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000); + tv.tv_sec = usec / 1000000; + tv.tv_usec = usec % 1000000; + return &tv; +} + +void select_reactor::cancel_ops_unlocked(socket_type descriptor, + const asio::error_code& ec) +{ + bool need_interrupt = false; + op_queue<operation> ops; + for (int i = 0; i < max_ops; ++i) + need_interrupt = op_queue_[i].cancel_operations( + descriptor, ops, ec) || need_interrupt; + io_service_.post_deferred_completions(ops); + if (need_interrupt) + interrupter_.interrupt(); +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_IOCP) + // || (!defined(ASIO_HAS_DEV_POLL) + // && !defined(ASIO_HAS_EPOLL) + // && !defined(ASIO_HAS_KQUEUE)) + // && !defined(ASIO_WINDOWS_RUNTIME)) + +#endif // ASIO_DETAIL_IMPL_SELECT_REACTOR_IPP diff --git a/asio-1.10.6/include/asio/detail/impl/service_registry.hpp b/asio-1.10.6/include/asio/detail/impl/service_registry.hpp new file mode 100644 index 0000000..01ff5ef --- /dev/null +++ b/asio-1.10.6/include/asio/detail/impl/service_registry.hpp @@ -0,0 +1,85 @@ +// +// detail/impl/service_registry.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IMPL_SERVICE_REGISTRY_HPP +#define ASIO_DETAIL_IMPL_SERVICE_REGISTRY_HPP + + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename Service, typename Arg> +service_registry::service_registry( + asio::io_service& o, Service*, Arg arg) + : owner_(o), + first_service_(new Service(o, arg)) +{ + asio::io_service::service::key key; + init_key(key, Service::id); + first_service_->key_ = key; + first_service_->next_ = 0; +} + +template <typename Service> +Service& service_registry::first_service() +{ + return *static_cast<Service*>(first_service_); +} + +template <typename Service> +Service& service_registry::use_service() +{ + asio::io_service::service::key key; + init_key(key, Service::id); + factory_type factory = &service_registry::create<Service>; + return *static_cast<Service*>(do_use_service(key, factory)); +} + +template <typename Service> +void service_registry::add_service(Service* new_service) +{ + asio::io_service::service::key key; + init_key(key, Service::id); + return do_add_service(key, new_service); +} + +template <typename Service> +bool service_registry::has_service() const +{ + asio::io_service::service::key key; + init_key(key, Service::id); + return do_has_service(key); +} + +#if !defined(ASIO_NO_TYPEID) +template <typename Service> +void service_registry::init_key(asio::io_service::service::key& key, + const asio::detail::service_id<Service>& /*id*/) +{ + key.type_info_ = &typeid(typeid_wrapper<Service>); + key.id_ = 0; +} +#endif // !defined(ASIO_NO_TYPEID) + +template <typename Service> +asio::io_service::service* service_registry::create( + asio::io_service& owner) +{ + return new Service(owner); +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_IMPL_SERVICE_REGISTRY_HPP diff --git a/asio-1.10.6/include/asio/detail/impl/service_registry.ipp b/asio-1.10.6/include/asio/detail/impl/service_registry.ipp new file mode 100644 index 0000000..281bce7 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/impl/service_registry.ipp @@ -0,0 +1,185 @@ +// +// detail/impl/service_registry.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IMPL_SERVICE_REGISTRY_IPP +#define ASIO_DETAIL_IMPL_SERVICE_REGISTRY_IPP + + +#include "asio/detail/config.hpp" +#include <vector> +#include "asio/detail/service_registry.hpp" +#include "asio/detail/throw_exception.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +service_registry::~service_registry() +{ + // Shutdown all services. This must be done in a separate loop before the + // services are destroyed since the destructors of user-defined handler + // objects may try to access other service objects. + asio::io_service::service* service = first_service_; + while (service) + { + service->shutdown_service(); + service = service->next_; + } + + // Destroy all services. + while (first_service_) + { + asio::io_service::service* next_service = first_service_->next_; + destroy(first_service_); + first_service_ = next_service; + } +} + +void service_registry::notify_fork(asio::io_service::fork_event fork_ev) +{ + // Make a copy of all of the services while holding the lock. We don't want + // to hold the lock while calling into each service, as it may try to call + // back into this class. + std::vector<asio::io_service::service*> services; + { + asio::detail::mutex::scoped_lock lock(mutex_); + asio::io_service::service* service = first_service_; + while (service) + { + services.push_back(service); + service = service->next_; + } + } + + // If processing the fork_prepare event, we want to go in reverse order of + // service registration, which happens to be the existing order of the + // services in the vector. For the other events we want to go in the other + // direction. + std::size_t num_services = services.size(); + if (fork_ev == asio::io_service::fork_prepare) + for (std::size_t i = 0; i < num_services; ++i) + services[i]->fork_service(fork_ev); + else + for (std::size_t i = num_services; i > 0; --i) + services[i - 1]->fork_service(fork_ev); +} + +void service_registry::init_key(asio::io_service::service::key& key, + const asio::io_service::id& id) +{ + key.type_info_ = 0; + key.id_ = &id; +} + +bool service_registry::keys_match( + const asio::io_service::service::key& key1, + const asio::io_service::service::key& key2) +{ + if (key1.id_ && key2.id_) + if (key1.id_ == key2.id_) + return true; + if (key1.type_info_ && key2.type_info_) + if (*key1.type_info_ == *key2.type_info_) + return true; + return false; +} + +void service_registry::destroy(asio::io_service::service* service) +{ + delete service; +} + +asio::io_service::service* service_registry::do_use_service( + const asio::io_service::service::key& key, + factory_type factory) +{ + asio::detail::mutex::scoped_lock lock(mutex_); + + // First see if there is an existing service object with the given key. + asio::io_service::service* service = first_service_; + while (service) + { + if (keys_match(service->key_, key)) + return service; + service = service->next_; + } + + // Create a new service object. The service registry's mutex is not locked + // at this time to allow for nested calls into this function from the new + // service's constructor. + lock.unlock(); + auto_service_ptr new_service = { factory(owner_) }; + new_service.ptr_->key_ = key; + lock.lock(); + + // Check that nobody else created another service object of the same type + // while the lock was released. + service = first_service_; + while (service) + { + if (keys_match(service->key_, key)) + return service; + service = service->next_; + } + + // Service was successfully initialised, pass ownership to registry. + new_service.ptr_->next_ = first_service_; + first_service_ = new_service.ptr_; + new_service.ptr_ = 0; + return first_service_; +} + +void service_registry::do_add_service( + const asio::io_service::service::key& key, + asio::io_service::service* new_service) +{ + if (&owner_ != &new_service->get_io_service()) + asio::detail::throw_exception(invalid_service_owner()); + + asio::detail::mutex::scoped_lock lock(mutex_); + + // Check if there is an existing service object with the given key. + asio::io_service::service* service = first_service_; + while (service) + { + if (keys_match(service->key_, key)) + asio::detail::throw_exception(service_already_exists()); + service = service->next_; + } + + // Take ownership of the service object. + new_service->key_ = key; + new_service->next_ = first_service_; + first_service_ = new_service; +} + +bool service_registry::do_has_service( + const asio::io_service::service::key& key) const +{ + asio::detail::mutex::scoped_lock lock(mutex_); + + asio::io_service::service* service = first_service_; + while (service) + { + if (keys_match(service->key_, key)) + return true; + service = service->next_; + } + + return false; +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_IMPL_SERVICE_REGISTRY_IPP diff --git a/asio-1.10.6/include/asio/detail/impl/socket_ops.ipp b/asio-1.10.6/include/asio/detail/impl/socket_ops.ipp new file mode 100644 index 0000000..306bcf8 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/impl/socket_ops.ipp @@ -0,0 +1,1581 @@ +// +// detail/impl/socket_ops.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_SOCKET_OPS_IPP +#define ASIO_DETAIL_SOCKET_OPS_IPP + + +#include "asio/detail/config.hpp" + +#include <cctype> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <cerrno> +#include <new> +#include "asio/detail/assert.hpp" +#include "asio/detail/socket_ops.hpp" +#include "asio/error.hpp" + + +#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) || defined(__MACH__) && defined(__APPLE__) +# if defined(ASIO_HAS_PTHREADS) +# include <pthread.h> +# endif // defined(ASIO_HAS_PTHREADS) +#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) + // || defined(__MACH__) && defined(__APPLE__) + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { +namespace socket_ops { + + + +#if defined(__hpux) +// HP-UX doesn't declare these functions extern "C", so they are declared again +// here to avoid linker errors about undefined symbols. +extern "C" char* if_indextoname(unsigned int, char*); +extern "C" unsigned int if_nametoindex(const char*); +#endif // defined(__hpux) + + +inline void clear_last_error() +{ + errno = 0; +} + + +template <typename ReturnType> +inline ReturnType error_wrapper(ReturnType return_value, + asio::error_code& ec) +{ + ec = asio::error_code(errno, + asio::error::get_system_category()); + return return_value; +} + +template <typename SockLenType> +inline socket_type call_accept(SockLenType msghdr::*, + socket_type s, socket_addr_type* addr, std::size_t* addrlen) +{ + SockLenType tmp_addrlen = addrlen ? (SockLenType)*addrlen : 0; + socket_type result = ::accept(s, addr, addrlen ? &tmp_addrlen : 0); + if (addrlen) + *addrlen = (std::size_t)tmp_addrlen; + return result; +} + +socket_type accept(socket_type s, socket_addr_type* addr, + std::size_t* addrlen, asio::error_code& ec) +{ + if (s == invalid_socket) + { + ec = asio::error::bad_descriptor; + return invalid_socket; + } + + clear_last_error(); + + socket_type new_s = error_wrapper(call_accept( + &msghdr::msg_namelen, s, addr, addrlen), ec); + if (new_s == invalid_socket) + return new_s; + +#if defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__) + int optval = 1; + int result = error_wrapper(::setsockopt(new_s, + SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec); + if (result != 0) + { + ::close(new_s); + return invalid_socket; + } +#endif + + ec = asio::error_code(); + return new_s; +} + +socket_type sync_accept(socket_type s, state_type state, + socket_addr_type* addr, std::size_t* addrlen, asio::error_code& ec) +{ + // Accept a socket. + for (;;) + { + // Try to complete the operation without blocking. + socket_type new_socket = socket_ops::accept(s, addr, addrlen, ec); + + // Check if operation succeeded. + if (new_socket != invalid_socket) + return new_socket; + + // Operation failed. + if (ec == asio::error::would_block + || ec == asio::error::try_again) + { + if (state & user_set_non_blocking) + return invalid_socket; + // Fall through to retry operation. + } + else if (ec == asio::error::connection_aborted) + { + if (state & enable_connection_aborted) + return invalid_socket; + // Fall through to retry operation. + } +#if defined(EPROTO) + else if (ec.value() == EPROTO) + { + if (state & enable_connection_aborted) + return invalid_socket; + // Fall through to retry operation. + } +#endif // defined(EPROTO) + else + return invalid_socket; + + // Wait for socket to become ready. + if (socket_ops::poll_read(s, 0, ec) < 0) + return invalid_socket; + } +} + + +bool non_blocking_accept(socket_type s, + state_type state, socket_addr_type* addr, std::size_t* addrlen, + asio::error_code& ec, socket_type& new_socket) +{ + for (;;) + { + // Accept the waiting connection. + new_socket = socket_ops::accept(s, addr, addrlen, ec); + + // Check if operation succeeded. + if (new_socket != invalid_socket) + return true; + + // Retry operation if interrupted by signal. + if (ec == asio::error::interrupted) + continue; + + // Operation failed. + if (ec == asio::error::would_block + || ec == asio::error::try_again) + { + if (state & user_set_non_blocking) + return true; + // Fall through to retry operation. + } + else if (ec == asio::error::connection_aborted) + { + if (state & enable_connection_aborted) + return true; + // Fall through to retry operation. + } +#if defined(EPROTO) + else if (ec.value() == EPROTO) + { + if (state & enable_connection_aborted) + return true; + // Fall through to retry operation. + } +#endif // defined(EPROTO) + else + return true; + + return false; + } +} + + +template <typename SockLenType> +inline int call_bind(SockLenType msghdr::*, + socket_type s, const socket_addr_type* addr, std::size_t addrlen) +{ + return ::bind(s, addr, (SockLenType)addrlen); +} + +int bind(socket_type s, const socket_addr_type* addr, + std::size_t addrlen, asio::error_code& ec) +{ + if (s == invalid_socket) + { + ec = asio::error::bad_descriptor; + return socket_error_retval; + } + + clear_last_error(); + int result = error_wrapper(call_bind( + &msghdr::msg_namelen, s, addr, addrlen), ec); + if (result == 0) + ec = asio::error_code(); + return result; +} + +int close(socket_type s, state_type& state, + bool destruction, asio::error_code& ec) +{ + int result = 0; + if (s != invalid_socket) + { + // We don't want the destructor to block, so set the socket to linger in + // the background. If the user doesn't like this behaviour then they need + // to explicitly close the socket. + if (destruction && (state & user_set_linger)) + { + ::linger opt; + opt.l_onoff = 0; + opt.l_linger = 0; + asio::error_code ignored_ec; + socket_ops::setsockopt(s, state, SOL_SOCKET, + SO_LINGER, &opt, sizeof(opt), ignored_ec); + } + + clear_last_error(); + result = error_wrapper(::close(s), ec); + + if (result != 0 + && (ec == asio::error::would_block + || ec == asio::error::try_again)) + { + // According to UNIX Network Programming Vol. 1, it is possible for + // close() to fail with EWOULDBLOCK under certain circumstances. What + // isn't clear is the state of the descriptor after this error. The one + // current OS where this behaviour is seen, Windows, says that the socket + // remains open. Therefore we'll put the descriptor back into blocking + // mode and have another attempt at closing it. + ioctl_arg_type arg = 0; + ::ioctl(s, FIONBIO, &arg); + state &= ~non_blocking; + + clear_last_error(); + result = error_wrapper(::close(s), ec); + } + } + + if (result == 0) + ec = asio::error_code(); + return result; +} + +bool set_user_non_blocking(socket_type s, + state_type& state, bool value, asio::error_code& ec) +{ + if (s == invalid_socket) + { + ec = asio::error::bad_descriptor; + return false; + } + + clear_last_error(); + ioctl_arg_type arg = (value ? 1 : 0); + int result = error_wrapper(::ioctl(s, FIONBIO, &arg), ec); + + if (result >= 0) + { + ec = asio::error_code(); + if (value) + state |= user_set_non_blocking; + else + { + // Clearing the user-set non-blocking mode always overrides any + // internally-set non-blocking flag. Any subsequent asynchronous + // operations will need to re-enable non-blocking I/O. + state &= ~(user_set_non_blocking | internal_non_blocking); + } + return true; + } + + return false; +} + +bool set_internal_non_blocking(socket_type s, + state_type& state, bool value, asio::error_code& ec) +{ + if (s == invalid_socket) + { + ec = asio::error::bad_descriptor; + return false; + } + + if (!value && (state & user_set_non_blocking)) + { + // It does not make sense to clear the internal non-blocking flag if the + // user still wants non-blocking behaviour. Return an error and let the + // caller figure out whether to update the user-set non-blocking flag. + ec = asio::error::invalid_argument; + return false; + } + + clear_last_error(); + ioctl_arg_type arg = (value ? 1 : 0); + int result = error_wrapper(::ioctl(s, FIONBIO, &arg), ec); + + if (result >= 0) + { + ec = asio::error_code(); + if (value) + state |= internal_non_blocking; + else + state &= ~internal_non_blocking; + return true; + } + + return false; +} + +int shutdown(socket_type s, int what, asio::error_code& ec) +{ + if (s == invalid_socket) + { + ec = asio::error::bad_descriptor; + return socket_error_retval; + } + + clear_last_error(); + int result = error_wrapper(::shutdown(s, what), ec); + if (result == 0) + ec = asio::error_code(); + return result; +} + +template <typename SockLenType> +inline int call_connect(SockLenType msghdr::*, + socket_type s, const socket_addr_type* addr, std::size_t addrlen) +{ + return ::connect(s, addr, (SockLenType)addrlen); +} + +int connect(socket_type s, const socket_addr_type* addr, + std::size_t addrlen, asio::error_code& ec) +{ + if (s == invalid_socket) + { + ec = asio::error::bad_descriptor; + return socket_error_retval; + } + + clear_last_error(); + int result = error_wrapper(call_connect( + &msghdr::msg_namelen, s, addr, addrlen), ec); + if (result == 0) + ec = asio::error_code(); +#if defined(__linux__) + else if (ec == asio::error::try_again) + ec = asio::error::no_buffer_space; +#endif // defined(__linux__) + return result; +} + +void sync_connect(socket_type s, const socket_addr_type* addr, + std::size_t addrlen, asio::error_code& ec) +{ + // Perform the connect operation. + socket_ops::connect(s, addr, addrlen, ec); + if (ec != asio::error::in_progress + && ec != asio::error::would_block) + { + // The connect operation finished immediately. + return; + } + + // Wait for socket to become ready. + if (socket_ops::poll_connect(s, ec) < 0) + return; + + // Get the error code from the connect operation. + int connect_error = 0; + size_t connect_error_len = sizeof(connect_error); + if (socket_ops::getsockopt(s, 0, SOL_SOCKET, SO_ERROR, + &connect_error, &connect_error_len, ec) == socket_error_retval) + return; + + // Return the result of the connect operation. + ec = asio::error_code(connect_error, + asio::error::get_system_category()); +} + + +bool non_blocking_connect(socket_type s, asio::error_code& ec) +{ + // Check if the connect operation has finished. This is required since we may + // get spurious readiness notifications from the reactor. + // || defined(__CYGWIN__) + // || defined(__SYMBIAN32__) + pollfd fds; + fds.fd = s; + fds.events = POLLOUT; + fds.revents = 0; + int ready = ::poll(&fds, 1, 0); + // || defined(__CYGWIN__) + // || defined(__SYMBIAN32__) + if (ready == 0) + { + // The asynchronous connect operation is still in progress. + return false; + } + + // Get the error code from the connect operation. + int connect_error = 0; + size_t connect_error_len = sizeof(connect_error); + if (socket_ops::getsockopt(s, 0, SOL_SOCKET, SO_ERROR, + &connect_error, &connect_error_len, ec) == 0) + { + if (connect_error) + { + ec = asio::error_code(connect_error, + asio::error::get_system_category()); + } + else + ec = asio::error_code(); + } + + return true; +} + +int socketpair(int af, int type, int protocol, + socket_type sv[2], asio::error_code& ec) +{ + clear_last_error(); + int result = error_wrapper(::socketpair(af, type, protocol, sv), ec); + if (result == 0) + ec = asio::error_code(); + return result; +} + +bool sockatmark(socket_type s, asio::error_code& ec) +{ + if (s == invalid_socket) + { + ec = asio::error::bad_descriptor; + return false; + } + +#if defined(SIOCATMARK) + ioctl_arg_type value = 0; + int result = error_wrapper(::ioctl(s, SIOCATMARK, &value), ec); + if (result == 0) + ec = asio::error_code(); +# if defined(ENOTTY) + if (ec.value() == ENOTTY) + ec = asio::error::not_socket; +# endif // defined(ENOTTY) +#else // defined(SIOCATMARK) + int value = error_wrapper(::sockatmark(s), ec); + if (value != -1) + ec = asio::error_code(); +#endif // defined(SIOCATMARK) + + return ec ? false : value != 0; +} + +size_t available(socket_type s, asio::error_code& ec) +{ + if (s == invalid_socket) + { + ec = asio::error::bad_descriptor; + return 0; + } + + ioctl_arg_type value = 0; + int result = error_wrapper(::ioctl(s, FIONREAD, &value), ec); + if (result == 0) + ec = asio::error_code(); +#if defined(ENOTTY) + if (ec.value() == ENOTTY) + ec = asio::error::not_socket; +#endif // defined(ENOTTY) + + return ec ? static_cast<size_t>(0) : static_cast<size_t>(value); +} + +int listen(socket_type s, int backlog, asio::error_code& ec) +{ + if (s == invalid_socket) + { + ec = asio::error::bad_descriptor; + return socket_error_retval; + } + + clear_last_error(); + int result = error_wrapper(::listen(s, backlog), ec); + if (result == 0) + ec = asio::error_code(); + return result; +} + +inline void init_buf_iov_base(void*& base, void* addr) +{ + base = addr; +} + +template <typename T> +inline void init_buf_iov_base(T& base, void* addr) +{ + base = static_cast<T>(addr); +} + +typedef iovec buf; + +void init_buf(buf& b, void* data, size_t size) +{ + init_buf_iov_base(b.iov_base, data); + b.iov_len = size; +} + +void init_buf(buf& b, const void* data, size_t size) +{ + init_buf_iov_base(b.iov_base, const_cast<void*>(data)); + b.iov_len = size; +} + +inline void init_msghdr_msg_name(void*& name, socket_addr_type* addr) +{ + name = addr; +} + +inline void init_msghdr_msg_name(void*& name, const socket_addr_type* addr) +{ + name = const_cast<socket_addr_type*>(addr); +} + +template <typename T> +inline void init_msghdr_msg_name(T& name, socket_addr_type* addr) +{ + name = reinterpret_cast<T>(addr); +} + +template <typename T> +inline void init_msghdr_msg_name(T& name, const socket_addr_type* addr) +{ + name = reinterpret_cast<T>(const_cast<socket_addr_type*>(addr)); +} + +signed_size_type recv(socket_type s, buf* bufs, size_t count, + int flags, asio::error_code& ec) +{ + clear_last_error(); + msghdr msg = msghdr(); + msg.msg_iov = bufs; + msg.msg_iovlen = static_cast<int>(count); + signed_size_type result = error_wrapper(::recvmsg(s, &msg, flags), ec); + if (result >= 0) + ec = asio::error_code(); + return result; +} + +size_t sync_recv(socket_type s, state_type state, buf* bufs, + size_t count, int flags, bool all_empty, asio::error_code& ec) +{ + if (s == invalid_socket) + { + ec = asio::error::bad_descriptor; + return 0; + } + + // A request to read 0 bytes on a stream is a no-op. + if (all_empty && (state & stream_oriented)) + { + ec = asio::error_code(); + return 0; + } + + // Read some data. + for (;;) + { + // Try to complete the operation without blocking. + signed_size_type bytes = socket_ops::recv(s, bufs, count, flags, ec); + + // Check if operation succeeded. + if (bytes > 0) + return bytes; + + // Check for EOF. + if ((state & stream_oriented) && bytes == 0) + { + ec = asio::error::eof; + return 0; + } + + // Operation failed. + if ((state & user_set_non_blocking) + || (ec != asio::error::would_block + && ec != asio::error::try_again)) + return 0; + + // Wait for socket to become ready. + if (socket_ops::poll_read(s, 0, ec) < 0) + return 0; + } +} + + +bool non_blocking_recv(socket_type s, + buf* bufs, size_t count, int flags, bool is_stream, + asio::error_code& ec, size_t& bytes_transferred) +{ + for (;;) + { + // Read some data. + signed_size_type bytes = socket_ops::recv(s, bufs, count, flags, ec); + + // Check for end of stream. + if (is_stream && bytes == 0) + { + ec = asio::error::eof; + return true; + } + + // Retry operation if interrupted by signal. + if (ec == asio::error::interrupted) + continue; + + // Check if we need to run the operation again. + if (ec == asio::error::would_block + || ec == asio::error::try_again) + return false; + + // Operation is complete. + if (bytes >= 0) + { + ec = asio::error_code(); + bytes_transferred = bytes; + } + else + bytes_transferred = 0; + + return true; + } +} + + +signed_size_type recvfrom(socket_type s, buf* bufs, size_t count, + int flags, socket_addr_type* addr, std::size_t* addrlen, + asio::error_code& ec) +{ + clear_last_error(); + msghdr msg = msghdr(); + init_msghdr_msg_name(msg.msg_name, addr); + msg.msg_namelen = static_cast<int>(*addrlen); + msg.msg_iov = bufs; + msg.msg_iovlen = static_cast<int>(count); + signed_size_type result = error_wrapper(::recvmsg(s, &msg, flags), ec); + *addrlen = msg.msg_namelen; + if (result >= 0) + ec = asio::error_code(); + return result; +} + +size_t sync_recvfrom(socket_type s, state_type state, buf* bufs, + size_t count, int flags, socket_addr_type* addr, + std::size_t* addrlen, asio::error_code& ec) +{ + if (s == invalid_socket) + { + ec = asio::error::bad_descriptor; + return 0; + } + + // Read some data. + for (;;) + { + // Try to complete the operation without blocking. + signed_size_type bytes = socket_ops::recvfrom( + s, bufs, count, flags, addr, addrlen, ec); + + // Check if operation succeeded. + if (bytes >= 0) + return bytes; + + // Operation failed. + if ((state & user_set_non_blocking) + || (ec != asio::error::would_block + && ec != asio::error::try_again)) + return 0; + + // Wait for socket to become ready. + if (socket_ops::poll_read(s, 0, ec) < 0) + return 0; + } +} + + +bool non_blocking_recvfrom(socket_type s, + buf* bufs, size_t count, int flags, + socket_addr_type* addr, std::size_t* addrlen, + asio::error_code& ec, size_t& bytes_transferred) +{ + for (;;) + { + // Read some data. + signed_size_type bytes = socket_ops::recvfrom( + s, bufs, count, flags, addr, addrlen, ec); + + // Retry operation if interrupted by signal. + if (ec == asio::error::interrupted) + continue; + + // Check if we need to run the operation again. + if (ec == asio::error::would_block + || ec == asio::error::try_again) + return false; + + // Operation is complete. + if (bytes >= 0) + { + ec = asio::error_code(); + bytes_transferred = bytes; + } + else + bytes_transferred = 0; + + return true; + } +} + + +signed_size_type recvmsg(socket_type s, buf* bufs, size_t count, + int in_flags, int& out_flags, asio::error_code& ec) +{ + clear_last_error(); + msghdr msg = msghdr(); + msg.msg_iov = bufs; + msg.msg_iovlen = static_cast<int>(count); + signed_size_type result = error_wrapper(::recvmsg(s, &msg, in_flags), ec); + if (result >= 0) + { + ec = asio::error_code(); + out_flags = msg.msg_flags; + } + else + out_flags = 0; + return result; +} + +size_t sync_recvmsg(socket_type s, state_type state, + buf* bufs, size_t count, int in_flags, int& out_flags, + asio::error_code& ec) +{ + if (s == invalid_socket) + { + ec = asio::error::bad_descriptor; + return 0; + } + + // Read some data. + for (;;) + { + // Try to complete the operation without blocking. + signed_size_type bytes = socket_ops::recvmsg( + s, bufs, count, in_flags, out_flags, ec); + + // Check if operation succeeded. + if (bytes >= 0) + return bytes; + + // Operation failed. + if ((state & user_set_non_blocking) + || (ec != asio::error::would_block + && ec != asio::error::try_again)) + return 0; + + // Wait for socket to become ready. + if (socket_ops::poll_read(s, 0, ec) < 0) + return 0; + } +} + + +bool non_blocking_recvmsg(socket_type s, + buf* bufs, size_t count, int in_flags, int& out_flags, + asio::error_code& ec, size_t& bytes_transferred) +{ + for (;;) + { + // Read some data. + signed_size_type bytes = socket_ops::recvmsg( + s, bufs, count, in_flags, out_flags, ec); + + // Retry operation if interrupted by signal. + if (ec == asio::error::interrupted) + continue; + + // Check if we need to run the operation again. + if (ec == asio::error::would_block + || ec == asio::error::try_again) + return false; + + // Operation is complete. + if (bytes >= 0) + { + ec = asio::error_code(); + bytes_transferred = bytes; + } + else + bytes_transferred = 0; + + return true; + } +} + + +signed_size_type send(socket_type s, const buf* bufs, size_t count, + int flags, asio::error_code& ec) +{ + clear_last_error(); + msghdr msg = msghdr(); + msg.msg_iov = const_cast<buf*>(bufs); + msg.msg_iovlen = static_cast<int>(count); +#if defined(__linux__) + flags |= MSG_NOSIGNAL; +#endif // defined(__linux__) + signed_size_type result = error_wrapper(::sendmsg(s, &msg, flags), ec); + if (result >= 0) + ec = asio::error_code(); + return result; +} + +size_t sync_send(socket_type s, state_type state, const buf* bufs, + size_t count, int flags, bool all_empty, asio::error_code& ec) +{ + if (s == invalid_socket) + { + ec = asio::error::bad_descriptor; + return 0; + } + + // A request to write 0 bytes to a stream is a no-op. + if (all_empty && (state & stream_oriented)) + { + ec = asio::error_code(); + return 0; + } + + // Read some data. + for (;;) + { + // Try to complete the operation without blocking. + signed_size_type bytes = socket_ops::send(s, bufs, count, flags, ec); + + // Check if operation succeeded. + if (bytes >= 0) + return bytes; + + // Operation failed. + if ((state & user_set_non_blocking) + || (ec != asio::error::would_block + && ec != asio::error::try_again)) + return 0; + + // Wait for socket to become ready. + if (socket_ops::poll_write(s, 0, ec) < 0) + return 0; + } +} + + +bool non_blocking_send(socket_type s, + const buf* bufs, size_t count, int flags, + asio::error_code& ec, size_t& bytes_transferred) +{ + for (;;) + { + // Write some data. + signed_size_type bytes = socket_ops::send(s, bufs, count, flags, ec); + + // Retry operation if interrupted by signal. + if (ec == asio::error::interrupted) + continue; + + // Check if we need to run the operation again. + if (ec == asio::error::would_block + || ec == asio::error::try_again) + return false; + + // Operation is complete. + if (bytes >= 0) + { + ec = asio::error_code(); + bytes_transferred = bytes; + } + else + bytes_transferred = 0; + + return true; + } +} + + +signed_size_type sendto(socket_type s, const buf* bufs, size_t count, + int flags, const socket_addr_type* addr, std::size_t addrlen, + asio::error_code& ec) +{ + clear_last_error(); + msghdr msg = msghdr(); + init_msghdr_msg_name(msg.msg_name, addr); + msg.msg_namelen = static_cast<int>(addrlen); + msg.msg_iov = const_cast<buf*>(bufs); + msg.msg_iovlen = static_cast<int>(count); +#if defined(__linux__) + flags |= MSG_NOSIGNAL; +#endif // defined(__linux__) + signed_size_type result = error_wrapper(::sendmsg(s, &msg, flags), ec); + if (result >= 0) + ec = asio::error_code(); + return result; +} + +size_t sync_sendto(socket_type s, state_type state, const buf* bufs, + size_t count, int flags, const socket_addr_type* addr, + std::size_t addrlen, asio::error_code& ec) +{ + if (s == invalid_socket) + { + ec = asio::error::bad_descriptor; + return 0; + } + + // Write some data. + for (;;) + { + // Try to complete the operation without blocking. + signed_size_type bytes = socket_ops::sendto( + s, bufs, count, flags, addr, addrlen, ec); + + // Check if operation succeeded. + if (bytes >= 0) + return bytes; + + // Operation failed. + if ((state & user_set_non_blocking) + || (ec != asio::error::would_block + && ec != asio::error::try_again)) + return 0; + + // Wait for socket to become ready. + if (socket_ops::poll_write(s, 0, ec) < 0) + return 0; + } +} + + +bool non_blocking_sendto(socket_type s, + const buf* bufs, size_t count, int flags, + const socket_addr_type* addr, std::size_t addrlen, + asio::error_code& ec, size_t& bytes_transferred) +{ + for (;;) + { + // Write some data. + signed_size_type bytes = socket_ops::sendto( + s, bufs, count, flags, addr, addrlen, ec); + + // Retry operation if interrupted by signal. + if (ec == asio::error::interrupted) + continue; + + // Check if we need to run the operation again. + if (ec == asio::error::would_block + || ec == asio::error::try_again) + return false; + + // Operation is complete. + if (bytes >= 0) + { + ec = asio::error_code(); + bytes_transferred = bytes; + } + else + bytes_transferred = 0; + + return true; + } +} + + +socket_type socket(int af, int type, int protocol, + asio::error_code& ec) +{ + clear_last_error(); +#if defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__) + socket_type s = error_wrapper(::socket(af, type, protocol), ec); + if (s == invalid_socket) + return s; + + int optval = 1; + int result = error_wrapper(::setsockopt(s, + SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec); + if (result != 0) + { + ::close(s); + return invalid_socket; + } + + return s; +#else + int s = error_wrapper(::socket(af, type, protocol), ec); + if (s >= 0) + ec = asio::error_code(); + return s; +#endif +} + +template <typename SockLenType> +inline int call_setsockopt(SockLenType msghdr::*, + socket_type s, int level, int optname, + const void* optval, std::size_t optlen) +{ + return ::setsockopt(s, level, optname, + (const char*)optval, (SockLenType)optlen); +} + +int setsockopt(socket_type s, state_type& state, int level, int optname, + const void* optval, std::size_t optlen, asio::error_code& ec) +{ + if (s == invalid_socket) + { + ec = asio::error::bad_descriptor; + return socket_error_retval; + } + + if (level == custom_socket_option_level && optname == always_fail_option) + { + ec = asio::error::invalid_argument; + return socket_error_retval; + } + + if (level == custom_socket_option_level + && optname == enable_connection_aborted_option) + { + if (optlen != sizeof(int)) + { + ec = asio::error::invalid_argument; + return socket_error_retval; + } + + if (*static_cast<const int*>(optval)) + state |= enable_connection_aborted; + else + state &= ~enable_connection_aborted; + ec = asio::error_code(); + return 0; + } + + if (level == SOL_SOCKET && optname == SO_LINGER) + state |= user_set_linger; + + clear_last_error(); + int result = error_wrapper(call_setsockopt(&msghdr::msg_namelen, + s, level, optname, optval, optlen), ec); + if (result == 0) + { + ec = asio::error_code(); + +#if defined(__MACH__) && defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) + // To implement portable behaviour for SO_REUSEADDR with UDP sockets we + // need to also set SO_REUSEPORT on BSD-based platforms. + if ((state & datagram_oriented) + && level == SOL_SOCKET && optname == SO_REUSEADDR) + { + call_setsockopt(&msghdr::msg_namelen, s, + SOL_SOCKET, SO_REUSEPORT, optval, optlen); + } +#endif + } + + return result; +} + +template <typename SockLenType> +inline int call_getsockopt(SockLenType msghdr::*, + socket_type s, int level, int optname, + void* optval, std::size_t* optlen) +{ + SockLenType tmp_optlen = (SockLenType)*optlen; + int result = ::getsockopt(s, level, optname, (char*)optval, &tmp_optlen); + *optlen = (std::size_t)tmp_optlen; + return result; +} + +int getsockopt(socket_type s, state_type state, int level, int optname, + void* optval, size_t* optlen, asio::error_code& ec) +{ + if (s == invalid_socket) + { + ec = asio::error::bad_descriptor; + return socket_error_retval; + } + + if (level == custom_socket_option_level && optname == always_fail_option) + { + ec = asio::error::invalid_argument; + return socket_error_retval; + } + + if (level == custom_socket_option_level + && optname == enable_connection_aborted_option) + { + if (*optlen != sizeof(int)) + { + ec = asio::error::invalid_argument; + return socket_error_retval; + } + + *static_cast<int*>(optval) = (state & enable_connection_aborted) ? 1 : 0; + ec = asio::error_code(); + return 0; + } + + clear_last_error(); + int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen, + s, level, optname, optval, optlen), ec); +#if defined(__linux__) + if (result == 0 && level == SOL_SOCKET && *optlen == sizeof(int) + && (optname == SO_SNDBUF || optname == SO_RCVBUF)) + { + // On Linux, setting SO_SNDBUF or SO_RCVBUF to N actually causes the kernel + // to set the buffer size to N*2. Linux puts additional stuff into the + // buffers so that only about half is actually available to the application. + // The retrieved value is divided by 2 here to make it appear as though the + // correct value has been set. + *static_cast<int*>(optval) /= 2; + } +#endif // defined(__linux__) + if (result == 0) + ec = asio::error_code(); + return result; +} + +template <typename SockLenType> +inline int call_getpeername(SockLenType msghdr::*, + socket_type s, socket_addr_type* addr, std::size_t* addrlen) +{ + SockLenType tmp_addrlen = (SockLenType)*addrlen; + int result = ::getpeername(s, addr, &tmp_addrlen); + *addrlen = (std::size_t)tmp_addrlen; + return result; +} + +int getpeername(socket_type s, socket_addr_type* addr, + std::size_t* addrlen, bool cached, asio::error_code& ec) +{ + if (s == invalid_socket) + { + ec = asio::error::bad_descriptor; + return socket_error_retval; + } + + (void)cached; + + clear_last_error(); + int result = error_wrapper(call_getpeername( + &msghdr::msg_namelen, s, addr, addrlen), ec); + if (result == 0) + ec = asio::error_code(); + return result; +} + +template <typename SockLenType> +inline int call_getsockname(SockLenType msghdr::*, + socket_type s, socket_addr_type* addr, std::size_t* addrlen) +{ + SockLenType tmp_addrlen = (SockLenType)*addrlen; + int result = ::getsockname(s, addr, &tmp_addrlen); + *addrlen = (std::size_t)tmp_addrlen; + return result; +} + +int getsockname(socket_type s, socket_addr_type* addr, + std::size_t* addrlen, asio::error_code& ec) +{ + if (s == invalid_socket) + { + ec = asio::error::bad_descriptor; + return socket_error_retval; + } + + clear_last_error(); + int result = error_wrapper(call_getsockname( + &msghdr::msg_namelen, s, addr, addrlen), ec); + if (result == 0) + ec = asio::error_code(); + return result; +} + +int ioctl(socket_type s, state_type& state, int cmd, + ioctl_arg_type* arg, asio::error_code& ec) +{ + if (s == invalid_socket) + { + ec = asio::error::bad_descriptor; + return socket_error_retval; + } + + clear_last_error(); +#if defined(__MACH__) && defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) + int result = error_wrapper(::ioctl(s, + static_cast<unsigned int>(cmd), arg), ec); +#else + int result = error_wrapper(::ioctl(s, cmd, arg), ec); +#endif + if (result >= 0) + { + ec = asio::error_code(); + + // When updating the non-blocking mode we always perform the ioctl syscall, + // even if the flags would otherwise indicate that the socket is already in + // the correct state. This ensures that the underlying socket is put into + // the state that has been requested by the user. If the ioctl syscall was + // successful then we need to update the flags to match. + if (cmd == static_cast<int>(FIONBIO)) + { + if (*arg) + { + state |= user_set_non_blocking; + } + else + { + // Clearing the non-blocking mode always overrides any internally-set + // non-blocking flag. Any subsequent asynchronous operations will need + // to re-enable non-blocking I/O. + state &= ~(user_set_non_blocking | internal_non_blocking); + } + } + } + + return result; +} + +int select(int nfds, fd_set* readfds, fd_set* writefds, + fd_set* exceptfds, timeval* timeout, asio::error_code& ec) +{ + clear_last_error(); + +#if defined(__hpux) && defined(__SELECT) + timespec ts; + ts.tv_sec = timeout ? timeout->tv_sec : 0; + ts.tv_nsec = timeout ? timeout->tv_usec * 1000 : 0; + return error_wrapper(::pselect(nfds, readfds, + writefds, exceptfds, timeout ? &ts : 0, 0), ec); +#else + int result = error_wrapper(::select(nfds, readfds, + writefds, exceptfds, timeout), ec); + if (result >= 0) + ec = asio::error_code(); + return result; +#endif +} + +int poll_read(socket_type s, state_type state, asio::error_code& ec) +{ + if (s == invalid_socket) + { + ec = asio::error::bad_descriptor; + return socket_error_retval; + } + + // || defined(__CYGWIN__) + // || defined(__SYMBIAN32__) + pollfd fds; + fds.fd = s; + fds.events = POLLIN; + fds.revents = 0; + int timeout = (state & user_set_non_blocking) ? 0 : -1; + clear_last_error(); + int result = error_wrapper(::poll(&fds, 1, timeout), ec); + // || defined(__CYGWIN__) + // || defined(__SYMBIAN32__) + if (result == 0) + ec = (state & user_set_non_blocking) + ? asio::error::would_block : asio::error_code(); + else if (result > 0) + ec = asio::error_code(); + return result; +} + +int poll_write(socket_type s, state_type state, asio::error_code& ec) +{ + if (s == invalid_socket) + { + ec = asio::error::bad_descriptor; + return socket_error_retval; + } + + // || defined(__CYGWIN__) + // || defined(__SYMBIAN32__) + pollfd fds; + fds.fd = s; + fds.events = POLLOUT; + fds.revents = 0; + int timeout = (state & user_set_non_blocking) ? 0 : -1; + clear_last_error(); + int result = error_wrapper(::poll(&fds, 1, timeout), ec); + // || defined(__CYGWIN__) + // || defined(__SYMBIAN32__) + if (result == 0) + ec = (state & user_set_non_blocking) + ? asio::error::would_block : asio::error_code(); + else if (result > 0) + ec = asio::error_code(); + return result; +} + +int poll_connect(socket_type s, asio::error_code& ec) +{ + if (s == invalid_socket) + { + ec = asio::error::bad_descriptor; + return socket_error_retval; + } + + // || defined(__CYGWIN__) + // || defined(__SYMBIAN32__) + pollfd fds; + fds.fd = s; + fds.events = POLLOUT; + fds.revents = 0; + clear_last_error(); + int result = error_wrapper(::poll(&fds, 1, -1), ec); + if (result >= 0) + ec = asio::error_code(); + return result; + // || defined(__CYGWIN__) + // || defined(__SYMBIAN32__) +} + + +const char* inet_ntop(int af, const void* src, char* dest, size_t length, + unsigned long scope_id, asio::error_code& ec) +{ + clear_last_error(); + const char* result = error_wrapper(::inet_ntop( + af, src, dest, static_cast<int>(length)), ec); + if (result == 0 && !ec) + ec = asio::error::invalid_argument; + if (result != 0 && af == ASIO_OS_DEF(AF_INET6) && scope_id != 0) + { + using namespace std; // For strcat and sprintf. + char if_name[IF_NAMESIZE + 1] = "%"; + const in6_addr_type* ipv6_address = static_cast<const in6_addr_type*>(src); + bool is_link_local = ((ipv6_address->s6_addr[0] == 0xfe) + && ((ipv6_address->s6_addr[1] & 0xc0) == 0x80)); + bool is_multicast_link_local = ((ipv6_address->s6_addr[0] == 0xff) + && ((ipv6_address->s6_addr[1] & 0x0f) == 0x02)); + if ((!is_link_local && !is_multicast_link_local) + || if_indextoname(static_cast<unsigned>(scope_id), if_name + 1) == 0) + sprintf(if_name + 1, "%lu", scope_id); + strcat(dest, if_name); + } + return result; +} + +int inet_pton(int af, const char* src, void* dest, + unsigned long* scope_id, asio::error_code& ec) +{ + clear_last_error(); + using namespace std; // For strchr, memcpy and atoi. + + // On some platforms, inet_pton fails if an address string contains a scope + // id. Detect and remove the scope id before passing the string to inet_pton. + const bool is_v6 = (af == ASIO_OS_DEF(AF_INET6)); + const char* if_name = is_v6 ? strchr(src, '%') : 0; + char src_buf[max_addr_v6_str_len + 1]; + const char* src_ptr = src; + if (if_name != 0) + { + if (if_name - src > max_addr_v6_str_len) + { + ec = asio::error::invalid_argument; + return 0; + } + memcpy(src_buf, src, if_name - src); + src_buf[if_name - src] = 0; + src_ptr = src_buf; + } + + int result = error_wrapper(::inet_pton(af, src_ptr, dest), ec); + if (result <= 0 && !ec) + ec = asio::error::invalid_argument; + if (result > 0 && is_v6 && scope_id) + { + using namespace std; // For strchr and atoi. + *scope_id = 0; + if (if_name != 0) + { + in6_addr_type* ipv6_address = static_cast<in6_addr_type*>(dest); + bool is_link_local = ((ipv6_address->s6_addr[0] == 0xfe) + && ((ipv6_address->s6_addr[1] & 0xc0) == 0x80)); + bool is_multicast_link_local = ((ipv6_address->s6_addr[0] == 0xff) + && ((ipv6_address->s6_addr[1] & 0x0f) == 0x02)); + if (is_link_local || is_multicast_link_local) + *scope_id = if_nametoindex(if_name + 1); + if (*scope_id == 0) + *scope_id = atoi(if_name + 1); + } + } + return result; +} + +int gethostname(char* name, int namelen, asio::error_code& ec) +{ + clear_last_error(); + int result = error_wrapper(::gethostname(name, namelen), ec); + return result; +} + + + +inline asio::error_code translate_addrinfo_error(int error) +{ + switch (error) + { + case 0: + return asio::error_code(); + case EAI_AGAIN: + return asio::error::host_not_found_try_again; + case EAI_BADFLAGS: + return asio::error::invalid_argument; + case EAI_FAIL: + return asio::error::no_recovery; + case EAI_FAMILY: + return asio::error::address_family_not_supported; + case EAI_MEMORY: + return asio::error::no_memory; + case EAI_NONAME: +#if defined(EAI_ADDRFAMILY) + case EAI_ADDRFAMILY: +#endif +#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) + case EAI_NODATA: +#endif + return asio::error::host_not_found; + case EAI_SERVICE: + return asio::error::service_not_found; + case EAI_SOCKTYPE: + return asio::error::socket_type_not_supported; + default: // Possibly the non-portable EAI_SYSTEM. + return asio::error_code( + errno, asio::error::get_system_category()); + } +} + +asio::error_code getaddrinfo(const char* host, + const char* service, const addrinfo_type& hints, + addrinfo_type** result, asio::error_code& ec) +{ + host = (host && *host) ? host : 0; + service = (service && *service) ? service : 0; + clear_last_error(); + int error = ::getaddrinfo(host, service, &hints, result); + return ec = translate_addrinfo_error(error); +} + +asio::error_code background_getaddrinfo( + const weak_cancel_token_type& cancel_token, const char* host, + const char* service, const addrinfo_type& hints, + addrinfo_type** result, asio::error_code& ec) +{ + if (cancel_token.expired()) + ec = asio::error::operation_aborted; + else + socket_ops::getaddrinfo(host, service, hints, result, ec); + return ec; +} + +void freeaddrinfo(addrinfo_type* ai) +{ + ::freeaddrinfo(ai); +} + +asio::error_code getnameinfo(const socket_addr_type* addr, + std::size_t addrlen, char* host, std::size_t hostlen, + char* serv, std::size_t servlen, int flags, asio::error_code& ec) +{ + clear_last_error(); + int error = ::getnameinfo(addr, addrlen, host, hostlen, serv, servlen, flags); + return ec = translate_addrinfo_error(error); +} + +asio::error_code sync_getnameinfo( + const socket_addr_type* addr, std::size_t addrlen, + char* host, std::size_t hostlen, char* serv, + std::size_t servlen, int sock_type, asio::error_code& ec) +{ + // First try resolving with the service name. If that fails try resolving + // but allow the service to be returned as a number. + int flags = (sock_type == SOCK_DGRAM) ? NI_DGRAM : 0; + socket_ops::getnameinfo(addr, addrlen, host, + hostlen, serv, servlen, flags, ec); + if (ec) + { + socket_ops::getnameinfo(addr, addrlen, host, hostlen, + serv, servlen, flags | NI_NUMERICSERV, ec); + } + + return ec; +} + +asio::error_code background_getnameinfo( + const weak_cancel_token_type& cancel_token, + const socket_addr_type* addr, std::size_t addrlen, + char* host, std::size_t hostlen, char* serv, + std::size_t servlen, int sock_type, asio::error_code& ec) +{ + if (cancel_token.expired()) + { + ec = asio::error::operation_aborted; + } + else + { + // First try resolving with the service name. If that fails try resolving + // but allow the service to be returned as a number. + int flags = (sock_type == SOCK_DGRAM) ? NI_DGRAM : 0; + socket_ops::getnameinfo(addr, addrlen, host, + hostlen, serv, servlen, flags, ec); + if (ec) + { + socket_ops::getnameinfo(addr, addrlen, host, hostlen, + serv, servlen, flags | NI_NUMERICSERV, ec); + } + } + + return ec; +} + + +u_long_type network_to_host_long(u_long_type value) +{ + return ntohl(value); +} + +u_long_type host_to_network_long(u_long_type value) +{ + return htonl(value); +} + +u_short_type network_to_host_short(u_short_type value) +{ + return ntohs(value); +} + +u_short_type host_to_network_short(u_short_type value) +{ + return htons(value); +} + +} // namespace socket_ops +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_SOCKET_OPS_IPP diff --git a/asio-1.10.6/include/asio/detail/impl/task_io_service.hpp b/asio-1.10.6/include/asio/detail/impl/task_io_service.hpp new file mode 100644 index 0000000..400c4fb --- /dev/null +++ b/asio-1.10.6/include/asio/detail/impl/task_io_service.hpp @@ -0,0 +1,75 @@ +// +// detail/impl/task_io_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IMPL_TASK_IO_SERVICE_HPP +#define ASIO_DETAIL_IMPL_TASK_IO_SERVICE_HPP + + +#include "asio/detail/addressof.hpp" +#include "asio/detail/completion_handler.hpp" +#include "asio/detail/fenced_block.hpp" +#include "asio/detail/handler_alloc_helpers.hpp" +#include "asio/detail/handler_cont_helpers.hpp" +#include "asio/detail/handler_invoke_helpers.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename Handler> +void task_io_service::dispatch(Handler& handler) +{ + if (thread_call_stack::contains(this)) + { + fenced_block b(fenced_block::full); + asio_handler_invoke_helpers::invoke(handler, handler); + } + else + { + // Allocate and construct an operation to wrap the handler. + typedef completion_handler<Handler> op; + typename op::ptr p = { asio::detail::addressof(handler), + asio_handler_alloc_helpers::allocate( + sizeof(op), handler), 0 }; + p.p = new (p.v) op(handler); + + ASIO_HANDLER_CREATION((p.p, "io_service", this, "dispatch")); + + do_dispatch(p.p); + p.v = p.p = 0; + } +} + +template <typename Handler> +void task_io_service::post(Handler& handler) +{ + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef completion_handler<Handler> op; + typename op::ptr p = { asio::detail::addressof(handler), + asio_handler_alloc_helpers::allocate( + sizeof(op), handler), 0 }; + p.p = new (p.v) op(handler); + + ASIO_HANDLER_CREATION((p.p, "io_service", this, "post")); + + post_immediate_completion(p.p, is_continuation); + p.v = p.p = 0; +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_IMPL_TASK_IO_SERVICE_HPP diff --git a/asio-1.10.6/include/asio/detail/impl/task_io_service.ipp b/asio-1.10.6/include/asio/detail/impl/task_io_service.ipp new file mode 100644 index 0000000..5c2b8c9 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/impl/task_io_service.ipp @@ -0,0 +1,455 @@ +// +// detail/impl/task_io_service.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IMPL_TASK_IO_SERVICE_IPP +#define ASIO_DETAIL_IMPL_TASK_IO_SERVICE_IPP + + +#include "asio/detail/config.hpp" + + +#include "asio/detail/event.hpp" +#include "asio/detail/limits.hpp" +#include "asio/detail/reactor.hpp" +#include "asio/detail/task_io_service.hpp" +#include "asio/detail/task_io_service_thread_info.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +struct task_io_service::task_cleanup +{ + ~task_cleanup() + { + if (this_thread_->private_outstanding_work > 0) + { + asio::detail::increment( + task_io_service_->outstanding_work_, + this_thread_->private_outstanding_work); + } + this_thread_->private_outstanding_work = 0; + + // Enqueue the completed operations and reinsert the task at the end of + // the operation queue. + lock_->lock(); + task_io_service_->task_interrupted_ = true; + task_io_service_->op_queue_.push(this_thread_->private_op_queue); + task_io_service_->op_queue_.push(&task_io_service_->task_operation_); + } + + task_io_service* task_io_service_; + mutex::scoped_lock* lock_; + thread_info* this_thread_; +}; + +struct task_io_service::work_cleanup +{ + ~work_cleanup() + { + if (this_thread_->private_outstanding_work > 1) + { + asio::detail::increment( + task_io_service_->outstanding_work_, + this_thread_->private_outstanding_work - 1); + } + else if (this_thread_->private_outstanding_work < 1) + { + task_io_service_->work_finished(); + } + this_thread_->private_outstanding_work = 0; + + if (!this_thread_->private_op_queue.empty()) + { + lock_->lock(); + task_io_service_->op_queue_.push(this_thread_->private_op_queue); + } + } + + task_io_service* task_io_service_; + mutex::scoped_lock* lock_; + thread_info* this_thread_; +}; + +task_io_service::task_io_service( + asio::io_service& io_service, std::size_t concurrency_hint) + : asio::detail::service_base<task_io_service>(io_service), + one_thread_(concurrency_hint == 1), + mutex_(), + task_(0), + task_interrupted_(true), + outstanding_work_(0), + stopped_(false), + shutdown_(false) +{ + ASIO_HANDLER_TRACKING_INIT; +} + +void task_io_service::shutdown_service() +{ + mutex::scoped_lock lock(mutex_); + shutdown_ = true; + lock.unlock(); + + // Destroy handler objects. + while (!op_queue_.empty()) + { + operation* o = op_queue_.front(); + op_queue_.pop(); + if (o != &task_operation_) + o->destroy(); + } + + // Reset to initial state. + task_ = 0; +} + +void task_io_service::init_task() +{ + mutex::scoped_lock lock(mutex_); + if (!shutdown_ && !task_) + { + task_ = &use_service<reactor>(this->get_io_service()); + op_queue_.push(&task_operation_); + wake_one_thread_and_unlock(lock); + } +} + +std::size_t task_io_service::run(asio::error_code& ec) +{ + ec = asio::error_code(); + if (outstanding_work_ == 0) + { + stop(); + return 0; + } + + thread_info this_thread; + this_thread.private_outstanding_work = 0; + thread_call_stack::context ctx(this, this_thread); + + mutex::scoped_lock lock(mutex_); + + std::size_t n = 0; + for (; do_run_one(lock, this_thread, ec); lock.lock()) + if (n != (std::numeric_limits<std::size_t>::max)()) + ++n; + return n; +} + +std::size_t task_io_service::run_one(asio::error_code& ec) +{ + ec = asio::error_code(); + if (outstanding_work_ == 0) + { + stop(); + return 0; + } + + thread_info this_thread; + this_thread.private_outstanding_work = 0; + thread_call_stack::context ctx(this, this_thread); + + mutex::scoped_lock lock(mutex_); + + return do_run_one(lock, this_thread, ec); +} + +std::size_t task_io_service::poll(asio::error_code& ec) +{ + ec = asio::error_code(); + if (outstanding_work_ == 0) + { + stop(); + return 0; + } + + thread_info this_thread; + this_thread.private_outstanding_work = 0; + thread_call_stack::context ctx(this, this_thread); + + mutex::scoped_lock lock(mutex_); + + // We want to support nested calls to poll() and poll_one(), so any handlers + // that are already on a thread-private queue need to be put on to the main + // queue now. + if (one_thread_) + if (thread_info* outer_thread_info = ctx.next_by_key()) + op_queue_.push(outer_thread_info->private_op_queue); + + std::size_t n = 0; + for (; do_poll_one(lock, this_thread, ec); lock.lock()) + if (n != (std::numeric_limits<std::size_t>::max)()) + ++n; + return n; +} + +std::size_t task_io_service::poll_one(asio::error_code& ec) +{ + ec = asio::error_code(); + if (outstanding_work_ == 0) + { + stop(); + return 0; + } + + thread_info this_thread; + this_thread.private_outstanding_work = 0; + thread_call_stack::context ctx(this, this_thread); + + mutex::scoped_lock lock(mutex_); + + // We want to support nested calls to poll() and poll_one(), so any handlers + // that are already on a thread-private queue need to be put on to the main + // queue now. + if (one_thread_) + if (thread_info* outer_thread_info = ctx.next_by_key()) + op_queue_.push(outer_thread_info->private_op_queue); + + return do_poll_one(lock, this_thread, ec); +} + +void task_io_service::stop() +{ + mutex::scoped_lock lock(mutex_); + stop_all_threads(lock); +} + +bool task_io_service::stopped() const +{ + mutex::scoped_lock lock(mutex_); + return stopped_; +} + +void task_io_service::reset() +{ + mutex::scoped_lock lock(mutex_); + stopped_ = false; +} + +void task_io_service::post_immediate_completion( + task_io_service::operation* op, bool is_continuation) +{ + if (one_thread_ || is_continuation) + { + if (thread_info* this_thread = thread_call_stack::contains(this)) + { + ++this_thread->private_outstanding_work; + this_thread->private_op_queue.push(op); + return; + } + } + + work_started(); + mutex::scoped_lock lock(mutex_); + op_queue_.push(op); + wake_one_thread_and_unlock(lock); +} + +void task_io_service::post_deferred_completion(task_io_service::operation* op) +{ + if (one_thread_) + { + if (thread_info* this_thread = thread_call_stack::contains(this)) + { + this_thread->private_op_queue.push(op); + return; + } + } + + mutex::scoped_lock lock(mutex_); + op_queue_.push(op); + wake_one_thread_and_unlock(lock); +} + +void task_io_service::post_deferred_completions( + op_queue<task_io_service::operation>& ops) +{ + if (!ops.empty()) + { + if (one_thread_) + { + if (thread_info* this_thread = thread_call_stack::contains(this)) + { + this_thread->private_op_queue.push(ops); + return; + } + } + + mutex::scoped_lock lock(mutex_); + op_queue_.push(ops); + wake_one_thread_and_unlock(lock); + } +} + +void task_io_service::do_dispatch( + task_io_service::operation* op) +{ + work_started(); + mutex::scoped_lock lock(mutex_); + op_queue_.push(op); + wake_one_thread_and_unlock(lock); +} + +void task_io_service::abandon_operations( + op_queue<task_io_service::operation>& ops) +{ + op_queue<task_io_service::operation> ops2; + ops2.push(ops); +} + +std::size_t task_io_service::do_run_one(mutex::scoped_lock& lock, + task_io_service::thread_info& this_thread, + const asio::error_code& ec) +{ + while (!stopped_) + { + if (!op_queue_.empty()) + { + // Prepare to execute first handler from queue. + operation* o = op_queue_.front(); + op_queue_.pop(); + bool more_handlers = (!op_queue_.empty()); + + if (o == &task_operation_) + { + task_interrupted_ = more_handlers; + + if (more_handlers && !one_thread_) + wakeup_event_.unlock_and_signal_one(lock); + else + lock.unlock(); + + task_cleanup on_exit = { this, &lock, &this_thread }; + (void)on_exit; + + // Run the task. May throw an exception. Only block if the operation + // queue is empty and we're not polling, otherwise we want to return + // as soon as possible. + task_->run(!more_handlers, this_thread.private_op_queue); + } + else + { + std::size_t task_result = o->task_result_; + + if (more_handlers && !one_thread_) + wake_one_thread_and_unlock(lock); + else + lock.unlock(); + + // Ensure the count of outstanding work is decremented on block exit. + work_cleanup on_exit = { this, &lock, &this_thread }; + (void)on_exit; + + // Complete the operation. May throw an exception. Deletes the object. + o->complete(*this, ec, task_result); + + return 1; + } + } + else + { + wakeup_event_.clear(lock); + wakeup_event_.wait(lock); + } + } + + return 0; +} + +std::size_t task_io_service::do_poll_one(mutex::scoped_lock& lock, + task_io_service::thread_info& this_thread, + const asio::error_code& ec) +{ + if (stopped_) + return 0; + + operation* o = op_queue_.front(); + if (o == &task_operation_) + { + op_queue_.pop(); + lock.unlock(); + + { + task_cleanup c = { this, &lock, &this_thread }; + (void)c; + + // Run the task. May throw an exception. Only block if the operation + // queue is empty and we're not polling, otherwise we want to return + // as soon as possible. + task_->run(false, this_thread.private_op_queue); + } + + o = op_queue_.front(); + if (o == &task_operation_) + { + wakeup_event_.maybe_unlock_and_signal_one(lock); + return 0; + } + } + + if (o == 0) + return 0; + + op_queue_.pop(); + bool more_handlers = (!op_queue_.empty()); + + std::size_t task_result = o->task_result_; + + if (more_handlers && !one_thread_) + wake_one_thread_and_unlock(lock); + else + lock.unlock(); + + // Ensure the count of outstanding work is decremented on block exit. + work_cleanup on_exit = { this, &lock, &this_thread }; + (void)on_exit; + + // Complete the operation. May throw an exception. Deletes the object. + o->complete(*this, ec, task_result); + + return 1; +} + +void task_io_service::stop_all_threads( + mutex::scoped_lock& lock) +{ + stopped_ = true; + wakeup_event_.signal_all(lock); + + if (!task_interrupted_ && task_) + { + task_interrupted_ = true; + task_->interrupt(); + } +} + +void task_io_service::wake_one_thread_and_unlock( + mutex::scoped_lock& lock) +{ + if (!wakeup_event_.maybe_unlock_and_signal_one(lock)) + { + if (!task_interrupted_ && task_) + { + task_interrupted_ = true; + task_->interrupt(); + } + lock.unlock(); + } +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + + +#endif // ASIO_DETAIL_IMPL_TASK_IO_SERVICE_IPP diff --git a/asio-1.10.6/include/asio/detail/impl/throw_error.ipp b/asio-1.10.6/include/asio/detail/impl/throw_error.ipp new file mode 100644 index 0000000..fccc204 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/impl/throw_error.ipp @@ -0,0 +1,46 @@ +// +// detail/impl/throw_error.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IMPL_THROW_ERROR_IPP +#define ASIO_DETAIL_IMPL_THROW_ERROR_IPP + + +#include "asio/detail/config.hpp" +#include "asio/detail/throw_error.hpp" +#include "asio/detail/throw_exception.hpp" +#include "asio/system_error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +void do_throw_error(const asio::error_code& err) +{ + asio::system_error e(err); + asio::detail::throw_exception(e); +} + +void do_throw_error(const asio::error_code& err, const char* location) +{ + // boostify: non-boost code starts here + // boostify: non-boost code ends here + asio::system_error e(err, location); + asio::detail::throw_exception(e); + // boostify: non-boost code starts here + // boostify: non-boost code ends here +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_IMPL_THROW_ERROR_IPP diff --git a/asio-1.10.6/include/asio/detail/impl/timer_queue_set.ipp b/asio-1.10.6/include/asio/detail/impl/timer_queue_set.ipp new file mode 100644 index 0000000..3d82b45 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/impl/timer_queue_set.ipp @@ -0,0 +1,98 @@ +// +// detail/impl/timer_queue_set.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IMPL_TIMER_QUEUE_SET_IPP +#define ASIO_DETAIL_IMPL_TIMER_QUEUE_SET_IPP + + +#include "asio/detail/config.hpp" +#include "asio/detail/timer_queue_set.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +timer_queue_set::timer_queue_set() + : first_(0) +{ +} + +void timer_queue_set::insert(timer_queue_base* q) +{ + q->next_ = first_; + first_ = q; +} + +void timer_queue_set::erase(timer_queue_base* q) +{ + if (first_) + { + if (q == first_) + { + first_ = q->next_; + q->next_ = 0; + return; + } + + for (timer_queue_base* p = first_; p->next_; p = p->next_) + { + if (p->next_ == q) + { + p->next_ = q->next_; + q->next_ = 0; + return; + } + } + } +} + +bool timer_queue_set::all_empty() const +{ + for (timer_queue_base* p = first_; p; p = p->next_) + if (!p->empty()) + return false; + return true; +} + +long timer_queue_set::wait_duration_msec(long max_duration) const +{ + long min_duration = max_duration; + for (timer_queue_base* p = first_; p; p = p->next_) + min_duration = p->wait_duration_msec(min_duration); + return min_duration; +} + +long timer_queue_set::wait_duration_usec(long max_duration) const +{ + long min_duration = max_duration; + for (timer_queue_base* p = first_; p; p = p->next_) + min_duration = p->wait_duration_usec(min_duration); + return min_duration; +} + +void timer_queue_set::get_ready_timers(op_queue<operation>& ops) +{ + for (timer_queue_base* p = first_; p; p = p->next_) + p->get_ready_timers(ops); +} + +void timer_queue_set::get_all_timers(op_queue<operation>& ops) +{ + for (timer_queue_base* p = first_; p; p = p->next_) + p->get_all_timers(ops); +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_IMPL_TIMER_QUEUE_SET_IPP diff --git a/asio-1.10.6/include/asio/detail/io_control.hpp b/asio-1.10.6/include/asio/detail/io_control.hpp new file mode 100644 index 0000000..0204bad --- /dev/null +++ b/asio-1.10.6/include/asio/detail/io_control.hpp @@ -0,0 +1,131 @@ +// +// detail/io_control.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IO_CONTROL_HPP +#define ASIO_DETAIL_IO_CONTROL_HPP + + +#include "asio/detail/config.hpp" +#include <cstddef> +#include "asio/detail/socket_types.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { +namespace io_control { + +// IO control command for non-blocking I/O. +class non_blocking_io +{ +public: + // Default constructor. + non_blocking_io() + : value_(0) + { + } + + // Construct with a specific command value. + non_blocking_io(bool value) + : value_(value ? 1 : 0) + { + } + + // Get the name of the IO control command. + int name() const + { + return static_cast<int>(ASIO_OS_DEF(FIONBIO)); + } + + // Set the value of the I/O control command. + void set(bool value) + { + value_ = value ? 1 : 0; + } + + // Get the current value of the I/O control command. + bool get() const + { + return value_ != 0; + } + + // Get the address of the command data. + detail::ioctl_arg_type* data() + { + return &value_; + } + + // Get the address of the command data. + const detail::ioctl_arg_type* data() const + { + return &value_; + } + +private: + detail::ioctl_arg_type value_; +}; + +// I/O control command for getting number of bytes available. +class bytes_readable +{ +public: + // Default constructor. + bytes_readable() + : value_(0) + { + } + + // Construct with a specific command value. + bytes_readable(std::size_t value) + : value_(static_cast<detail::ioctl_arg_type>(value)) + { + } + + // Get the name of the IO control command. + int name() const + { + return static_cast<int>(ASIO_OS_DEF(FIONREAD)); + } + + // Set the value of the I/O control command. + void set(std::size_t value) + { + value_ = static_cast<detail::ioctl_arg_type>(value); + } + + // Get the current value of the I/O control command. + std::size_t get() const + { + return static_cast<std::size_t>(value_); + } + + // Get the address of the command data. + detail::ioctl_arg_type* data() + { + return &value_; + } + + // Get the address of the command data. + const detail::ioctl_arg_type* data() const + { + return &value_; + } + +private: + detail::ioctl_arg_type value_; +}; + +} // namespace io_control +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_IO_CONTROL_HPP diff --git a/asio-1.10.6/include/asio/detail/limits.hpp b/asio-1.10.6/include/asio/detail/limits.hpp new file mode 100644 index 0000000..e20b8a3 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/limits.hpp @@ -0,0 +1,19 @@ +// +// detail/limits.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_LIMITS_HPP +#define ASIO_DETAIL_LIMITS_HPP + + +#include "asio/detail/config.hpp" + +# include <limits> + +#endif // ASIO_DETAIL_LIMITS_HPP diff --git a/asio-1.10.6/include/asio/detail/local_free_on_block_exit.hpp b/asio-1.10.6/include/asio/detail/local_free_on_block_exit.hpp new file mode 100644 index 0000000..bfca59e --- /dev/null +++ b/asio-1.10.6/include/asio/detail/local_free_on_block_exit.hpp @@ -0,0 +1,18 @@ +// +// detail/local_free_on_block_exit.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_LOCAL_FREE_ON_BLOCK_EXIT_HPP +#define ASIO_DETAIL_LOCAL_FREE_ON_BLOCK_EXIT_HPP + + +#include "asio/detail/config.hpp" + + +#endif // ASIO_DETAIL_LOCAL_FREE_ON_BLOCK_EXIT_HPP diff --git a/asio-1.10.6/include/asio/detail/mutex.hpp b/asio-1.10.6/include/asio/detail/mutex.hpp new file mode 100644 index 0000000..e744279 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/mutex.hpp @@ -0,0 +1,35 @@ +// +// detail/mutex.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_MUTEX_HPP +#define ASIO_DETAIL_MUTEX_HPP + + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_PTHREADS) +# include "asio/detail/posix_mutex.hpp" +#else +# include "asio/detail/std_mutex.hpp" +#endif + +namespace asio { +namespace detail { + +#if defined(ASIO_HAS_PTHREADS) +typedef posix_mutex mutex; +#else +typedef std_mutex mutex; +#endif + +} // namespace detail +} // namespace asio + +#endif // ASIO_DETAIL_MUTEX_HPP diff --git a/asio-1.10.6/include/asio/detail/noncopyable.hpp b/asio-1.10.6/include/asio/detail/noncopyable.hpp new file mode 100644 index 0000000..1e03bca --- /dev/null +++ b/asio-1.10.6/include/asio/detail/noncopyable.hpp @@ -0,0 +1,40 @@ +// +// detail/noncopyable.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_NONCOPYABLE_HPP +#define ASIO_DETAIL_NONCOPYABLE_HPP + + +#include "asio/detail/config.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class noncopyable +{ +protected: + noncopyable() {} + ~noncopyable() {} +private: + noncopyable(const noncopyable&); + const noncopyable& operator=(const noncopyable&); +}; + +} // namespace detail + +using asio::detail::noncopyable; + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_NONCOPYABLE_HPP diff --git a/asio-1.10.6/include/asio/detail/null_fenced_block.hpp b/asio-1.10.6/include/asio/detail/null_fenced_block.hpp new file mode 100644 index 0000000..e3dad8d --- /dev/null +++ b/asio-1.10.6/include/asio/detail/null_fenced_block.hpp @@ -0,0 +1,42 @@ +// +// detail/null_fenced_block.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_NULL_FENCED_BLOCK_HPP +#define ASIO_DETAIL_NULL_FENCED_BLOCK_HPP + + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class null_fenced_block + : private noncopyable +{ +public: + enum half_or_full_t { half, full }; + + // Constructor. + explicit null_fenced_block(half_or_full_t) + { + } + + // Destructor. + ~null_fenced_block() + { + } +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_NULL_FENCED_BLOCK_HPP diff --git a/asio-1.10.6/include/asio/detail/op_queue.hpp b/asio-1.10.6/include/asio/detail/op_queue.hpp new file mode 100644 index 0000000..ea67063 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/op_queue.hpp @@ -0,0 +1,153 @@ +// +// detail/op_queue.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_OP_QUEUE_HPP +#define ASIO_DETAIL_OP_QUEUE_HPP + + +#include "asio/detail/noncopyable.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename Operation> +class op_queue; + +class op_queue_access +{ +public: + template <typename Operation> + static Operation* next(Operation* o) + { + return static_cast<Operation*>(o->next_); + } + + template <typename Operation1, typename Operation2> + static void next(Operation1*& o1, Operation2* o2) + { + o1->next_ = o2; + } + + template <typename Operation> + static void destroy(Operation* o) + { + o->destroy(); + } + + template <typename Operation> + static Operation*& front(op_queue<Operation>& q) + { + return q.front_; + } + + template <typename Operation> + static Operation*& back(op_queue<Operation>& q) + { + return q.back_; + } +}; + +template <typename Operation> +class op_queue + : private noncopyable +{ +public: + // Constructor. + op_queue() + : front_(0), + back_(0) + { + } + + // Destructor destroys all operations. + ~op_queue() + { + while (Operation* op = front_) + { + pop(); + op_queue_access::destroy(op); + } + } + + // Get the operation at the front of the queue. + Operation* front() + { + return front_; + } + + // Pop an operation from the front of the queue. + void pop() + { + if (front_) + { + Operation* tmp = front_; + front_ = op_queue_access::next(front_); + if (front_ == 0) + back_ = 0; + op_queue_access::next(tmp, static_cast<Operation*>(0)); + } + } + + // Push an operation on to the back of the queue. + void push(Operation* h) + { + op_queue_access::next(h, static_cast<Operation*>(0)); + if (back_) + { + op_queue_access::next(back_, h); + back_ = h; + } + else + { + front_ = back_ = h; + } + } + + // Push all operations from another queue on to the back of the queue. The + // source queue may contain operations of a derived type. + template <typename OtherOperation> + void push(op_queue<OtherOperation>& q) + { + if (Operation* other_front = op_queue_access::front(q)) + { + if (back_) + op_queue_access::next(back_, other_front); + else + front_ = other_front; + back_ = op_queue_access::back(q); + op_queue_access::front(q) = 0; + op_queue_access::back(q) = 0; + } + } + + // Whether the queue is empty. + bool empty() const + { + return front_ == 0; + } + +private: + friend class op_queue_access; + + // The front of the queue. + Operation* front_; + + // The back of the queue. + Operation* back_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_OP_QUEUE_HPP diff --git a/asio-1.10.6/include/asio/detail/operation.hpp b/asio-1.10.6/include/asio/detail/operation.hpp new file mode 100644 index 0000000..2ca44ad --- /dev/null +++ b/asio-1.10.6/include/asio/detail/operation.hpp @@ -0,0 +1,27 @@ +// +// detail/operation.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_OPERATION_HPP +#define ASIO_DETAIL_OPERATION_HPP + + +#include "asio/detail/config.hpp" + +# include "asio/detail/task_io_service_operation.hpp" + +namespace asio { +namespace detail { + +typedef task_io_service_operation operation; + +} // namespace detail +} // namespace asio + +#endif // ASIO_DETAIL_OPERATION_HPP diff --git a/asio-1.10.6/include/asio/detail/pipe_select_interrupter.hpp b/asio-1.10.6/include/asio/detail/pipe_select_interrupter.hpp new file mode 100644 index 0000000..3dad932 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/pipe_select_interrupter.hpp @@ -0,0 +1,74 @@ +// +// detail/pipe_select_interrupter.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_PIPE_SELECT_INTERRUPTER_HPP +#define ASIO_DETAIL_PIPE_SELECT_INTERRUPTER_HPP + + +#include "asio/detail/config.hpp" + + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class pipe_select_interrupter +{ +public: + // Constructor. + ASIO_DECL pipe_select_interrupter(); + + // Destructor. + ASIO_DECL ~pipe_select_interrupter(); + + // Recreate the interrupter's descriptors. Used after a fork. + ASIO_DECL void recreate(); + + // Interrupt the select call. + ASIO_DECL void interrupt(); + + // Reset the select interrupt. Returns true if the call was interrupted. + ASIO_DECL bool reset(); + + // Get the read descriptor to be passed to select. + int read_descriptor() const + { + return read_descriptor_; + } + +private: + // Open the descriptors. Throws on error. + ASIO_DECL void open_descriptors(); + + // Close the descriptors. + ASIO_DECL void close_descriptors(); + + // The read end of a connection used to interrupt the select call. This file + // descriptor is passed to select such that when it is time to stop, a single + // byte will be written on the other end of the connection and this + // descriptor will become readable. + int read_descriptor_; + + // The write end of a connection used to interrupt the select call. A single + // byte may be written to this to wake up the select which is waiting for the + // other end to become readable. + int write_descriptor_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +# include "asio/detail/impl/pipe_select_interrupter.ipp" + + +#endif // ASIO_DETAIL_PIPE_SELECT_INTERRUPTER_HPP diff --git a/asio-1.10.6/include/asio/detail/pop_options.hpp b/asio-1.10.6/include/asio/detail/pop_options.hpp new file mode 100644 index 0000000..e8b941e --- /dev/null +++ b/asio-1.10.6/include/asio/detail/pop_options.hpp @@ -0,0 +1,45 @@ +// +// detail/pop_options.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +// No header guard + +#if defined(__COMO__) + +// Comeau C++ + +#elif defined(__DMC__) + +// Digital Mars C++ + +#elif defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC) + +// Intel C++ + +# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) +# pragma GCC visibility pop +# endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) + +#else + +// Clang + +# if defined(__OBJC__) +# if !defined(__APPLE_CC__) || (__APPLE_CC__ <= 1) +# if defined(ASIO_OBJC_WORKAROUND) +# undef Protocol +# undef id +# undef ASIO_OBJC_WORKAROUND +# endif +# endif +# endif + +# pragma GCC visibility pop + +#endif diff --git a/asio-1.10.6/include/asio/detail/posix_event.hpp b/asio-1.10.6/include/asio/detail/posix_event.hpp new file mode 100644 index 0000000..2e25e35 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/posix_event.hpp @@ -0,0 +1,121 @@ +// +// detail/posix_event.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_POSIX_EVENT_HPP +#define ASIO_DETAIL_POSIX_EVENT_HPP + + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_PTHREADS) + +#include <pthread.h> +#include "asio/detail/assert.hpp" +#include "asio/detail/noncopyable.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class posix_event + : private noncopyable +{ +public: + // Constructor. + ASIO_DECL posix_event(); + + // Destructor. + ~posix_event() + { + ::pthread_cond_destroy(&cond_); + } + + // Signal the event. (Retained for backward compatibility.) + template <typename Lock> + void signal(Lock& lock) + { + this->signal_all(lock); + } + + // Signal all waiters. + template <typename Lock> + void signal_all(Lock& lock) + { + ASIO_ASSERT(lock.locked()); + (void)lock; + state_ |= 1; + ::pthread_cond_broadcast(&cond_); // Ignore EINVAL. + } + + // Unlock the mutex and signal one waiter. + template <typename Lock> + void unlock_and_signal_one(Lock& lock) + { + ASIO_ASSERT(lock.locked()); + state_ |= 1; + bool have_waiters = (state_ > 1); + lock.unlock(); + if (have_waiters) + ::pthread_cond_signal(&cond_); // Ignore EINVAL. + } + + // If there's a waiter, unlock the mutex and signal it. + template <typename Lock> + bool maybe_unlock_and_signal_one(Lock& lock) + { + ASIO_ASSERT(lock.locked()); + state_ |= 1; + if (state_ > 1) + { + lock.unlock(); + ::pthread_cond_signal(&cond_); // Ignore EINVAL. + return true; + } + return false; + } + + // Reset the event. + template <typename Lock> + void clear(Lock& lock) + { + ASIO_ASSERT(lock.locked()); + (void)lock; + state_ &= ~std::size_t(1); + } + + // Wait for the event to become signalled. + template <typename Lock> + void wait(Lock& lock) + { + ASIO_ASSERT(lock.locked()); + while ((state_ & 1) == 0) + { + state_ += 2; + ::pthread_cond_wait(&cond_, &lock.mutex().mutex_); // Ignore EINVAL. + state_ -= 2; + } + } + +private: + ::pthread_cond_t cond_; + std::size_t state_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +# include "asio/detail/impl/posix_event.ipp" + +#endif // defined(ASIO_HAS_PTHREADS) + +#endif // ASIO_DETAIL_POSIX_EVENT_HPP diff --git a/asio-1.10.6/include/asio/detail/posix_fd_set_adapter.hpp b/asio-1.10.6/include/asio/detail/posix_fd_set_adapter.hpp new file mode 100644 index 0000000..9240ff6 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/posix_fd_set_adapter.hpp @@ -0,0 +1,111 @@ +// +// detail/posix_fd_set_adapter.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_POSIX_FD_SET_ADAPTER_HPP +#define ASIO_DETAIL_POSIX_FD_SET_ADAPTER_HPP + + +#include "asio/detail/config.hpp" + + +#include <cstring> +#include "asio/detail/noncopyable.hpp" +#include "asio/detail/reactor_op_queue.hpp" +#include "asio/detail/socket_types.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +// Adapts the FD_SET type to meet the Descriptor_Set concept's requirements. +class posix_fd_set_adapter : noncopyable +{ +public: + posix_fd_set_adapter() + : max_descriptor_(invalid_socket) + { + using namespace std; // Needed for memset on Solaris. + FD_ZERO(&fd_set_); + } + + void reset() + { + using namespace std; // Needed for memset on Solaris. + FD_ZERO(&fd_set_); + } + + bool set(socket_type descriptor) + { + if (descriptor < (socket_type)FD_SETSIZE) + { + if (max_descriptor_ == invalid_socket || descriptor > max_descriptor_) + max_descriptor_ = descriptor; + FD_SET(descriptor, &fd_set_); + return true; + } + return false; + } + + void set(reactor_op_queue<socket_type>& operations, op_queue<operation>& ops) + { + reactor_op_queue<socket_type>::iterator i = operations.begin(); + while (i != operations.end()) + { + reactor_op_queue<socket_type>::iterator op_iter = i++; + if (!set(op_iter->first)) + { + asio::error_code ec(error::fd_set_failure); + operations.cancel_operations(op_iter, ops, ec); + } + } + } + + bool is_set(socket_type descriptor) const + { + return FD_ISSET(descriptor, &fd_set_) != 0; + } + + operator fd_set*() + { + return &fd_set_; + } + + socket_type max_descriptor() const + { + return max_descriptor_; + } + + void perform(reactor_op_queue<socket_type>& operations, + op_queue<operation>& ops) const + { + reactor_op_queue<socket_type>::iterator i = operations.begin(); + while (i != operations.end()) + { + reactor_op_queue<socket_type>::iterator op_iter = i++; + if (is_set(op_iter->first)) + operations.perform_operations(op_iter, ops); + } + } + +private: + mutable fd_set fd_set_; + socket_type max_descriptor_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + + // && !defined(__CYGWIN__) + // && !defined(ASIO_WINDOWS_RUNTIME) + +#endif // ASIO_DETAIL_POSIX_FD_SET_ADAPTER_HPP diff --git a/asio-1.10.6/include/asio/detail/posix_mutex.hpp b/asio-1.10.6/include/asio/detail/posix_mutex.hpp new file mode 100644 index 0000000..bd69d58 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/posix_mutex.hpp @@ -0,0 +1,71 @@ +// +// detail/posix_mutex.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_POSIX_MUTEX_HPP +#define ASIO_DETAIL_POSIX_MUTEX_HPP + + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_PTHREADS) + +#include <pthread.h> +#include "asio/detail/noncopyable.hpp" +#include "asio/detail/scoped_lock.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class posix_event; + +class posix_mutex + : private noncopyable +{ +public: + typedef asio::detail::scoped_lock<posix_mutex> scoped_lock; + + // Constructor. + ASIO_DECL posix_mutex(); + + // Destructor. + ~posix_mutex() + { + ::pthread_mutex_destroy(&mutex_); // Ignore EBUSY. + } + + // Lock the mutex. + void lock() + { + (void)::pthread_mutex_lock(&mutex_); // Ignore EINVAL. + } + + // Unlock the mutex. + void unlock() + { + (void)::pthread_mutex_unlock(&mutex_); // Ignore EINVAL. + } + +private: + friend class posix_event; + ::pthread_mutex_t mutex_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +# include "asio/detail/impl/posix_mutex.ipp" + +#endif // defined(ASIO_HAS_PTHREADS) + +#endif // ASIO_DETAIL_POSIX_MUTEX_HPP diff --git a/asio-1.10.6/include/asio/detail/posix_signal_blocker.hpp b/asio-1.10.6/include/asio/detail/posix_signal_blocker.hpp new file mode 100644 index 0000000..6c3956f --- /dev/null +++ b/asio-1.10.6/include/asio/detail/posix_signal_blocker.hpp @@ -0,0 +1,82 @@ +// +// detail/posix_signal_blocker.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_POSIX_SIGNAL_BLOCKER_HPP +#define ASIO_DETAIL_POSIX_SIGNAL_BLOCKER_HPP + + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_PTHREADS) + +#include <csignal> +#include <pthread.h> +#include <signal.h> +#include "asio/detail/noncopyable.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class posix_signal_blocker + : private noncopyable +{ +public: + // Constructor blocks all signals for the calling thread. + posix_signal_blocker() + : blocked_(false) + { + sigset_t new_mask; + sigfillset(&new_mask); + blocked_ = (pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask_) == 0); + } + + // Destructor restores the previous signal mask. + ~posix_signal_blocker() + { + if (blocked_) + pthread_sigmask(SIG_SETMASK, &old_mask_, 0); + } + + // Block all signals for the calling thread. + void block() + { + if (!blocked_) + { + sigset_t new_mask; + sigfillset(&new_mask); + blocked_ = (pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask_) == 0); + } + } + + // Restore the previous signal mask. + void unblock() + { + if (blocked_) + blocked_ = (pthread_sigmask(SIG_SETMASK, &old_mask_, 0) != 0); + } + +private: + // Have signals been blocked. + bool blocked_; + + // The previous signal mask. + sigset_t old_mask_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_PTHREADS) + +#endif // ASIO_DETAIL_POSIX_SIGNAL_BLOCKER_HPP diff --git a/asio-1.10.6/include/asio/detail/posix_thread.hpp b/asio-1.10.6/include/asio/detail/posix_thread.hpp new file mode 100644 index 0000000..046b224 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/posix_thread.hpp @@ -0,0 +1,100 @@ +// +// detail/posix_thread.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_POSIX_THREAD_HPP +#define ASIO_DETAIL_POSIX_THREAD_HPP + + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_PTHREADS) + +#include <pthread.h> +#include "asio/detail/noncopyable.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +extern "C" +{ + ASIO_DECL void* asio_detail_posix_thread_function(void* arg); +} + +class posix_thread + : private noncopyable +{ +public: + // Constructor. + template <typename Function> + posix_thread(Function f, unsigned int = 0) + : joined_(false) + { + start_thread(new func<Function>(f)); + } + + // Destructor. + ASIO_DECL ~posix_thread(); + + // Wait for the thread to exit. + ASIO_DECL void join(); + +private: + friend void* asio_detail_posix_thread_function(void* arg); + + class func_base + { + public: + virtual ~func_base() {} + virtual void run() = 0; + }; + + struct auto_func_base_ptr + { + func_base* ptr; + ~auto_func_base_ptr() { delete ptr; } + }; + + template <typename Function> + class func + : public func_base + { + public: + func(Function f) + : f_(f) + { + } + + virtual void run() + { + f_(); + } + + private: + Function f_; + }; + + ASIO_DECL void start_thread(func_base* arg); + + ::pthread_t thread_; + bool joined_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +# include "asio/detail/impl/posix_thread.ipp" + +#endif // defined(ASIO_HAS_PTHREADS) + +#endif // ASIO_DETAIL_POSIX_THREAD_HPP diff --git a/asio-1.10.6/include/asio/detail/posix_tss_ptr.hpp b/asio-1.10.6/include/asio/detail/posix_tss_ptr.hpp new file mode 100644 index 0000000..57fdac2 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/posix_tss_ptr.hpp @@ -0,0 +1,74 @@ +// +// detail/posix_tss_ptr.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_POSIX_TSS_PTR_HPP +#define ASIO_DETAIL_POSIX_TSS_PTR_HPP + + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_PTHREADS) + +#include <pthread.h> +#include "asio/detail/noncopyable.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +// Helper function to create thread-specific storage. +ASIO_DECL void posix_tss_ptr_create(pthread_key_t& key); + +template <typename T> +class posix_tss_ptr + : private noncopyable +{ +public: + // Constructor. + posix_tss_ptr() + { + posix_tss_ptr_create(tss_key_); + } + + // Destructor. + ~posix_tss_ptr() + { + ::pthread_key_delete(tss_key_); + } + + // Get the value. + operator T*() const + { + return static_cast<T*>(::pthread_getspecific(tss_key_)); + } + + // Set the value. + void operator=(T* value) + { + ::pthread_setspecific(tss_key_, value); + } + +private: + // Thread-specific storage to allow unlocked access to determine whether a + // thread is a member of the pool. + pthread_key_t tss_key_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +# include "asio/detail/impl/posix_tss_ptr.ipp" + +#endif // defined(ASIO_HAS_PTHREADS) + +#endif // ASIO_DETAIL_POSIX_TSS_PTR_HPP diff --git a/asio-1.10.6/include/asio/detail/push_options.hpp b/asio-1.10.6/include/asio/detail/push_options.hpp new file mode 100644 index 0000000..6e2d6fa --- /dev/null +++ b/asio-1.10.6/include/asio/detail/push_options.hpp @@ -0,0 +1,47 @@ +// +// detail/push_options.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +// No header guard + +#if defined(__COMO__) + +// Comeau C++ + +#elif defined(__DMC__) + +// Digital Mars C++ + +#elif defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC) + +// Intel C++ + +# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) +# pragma GCC visibility push (default) +# endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) + +#else + +// Clang + +# if defined(__OBJC__) +# if !defined(__APPLE_CC__) || (__APPLE_CC__ <= 1) +# if !defined(ASIO_DISABLE_OBJC_WORKAROUND) +# if !defined(Protocol) && !defined(id) +# define Protocol cpp_Protocol +# define id cpp_id +# define ASIO_OBJC_WORKAROUND +# endif +# endif +# endif +# endif + +# pragma GCC visibility push (default) + +#endif diff --git a/asio-1.10.6/include/asio/detail/reactive_null_buffers_op.hpp b/asio-1.10.6/include/asio/detail/reactive_null_buffers_op.hpp new file mode 100644 index 0000000..f87010a --- /dev/null +++ b/asio-1.10.6/include/asio/detail/reactive_null_buffers_op.hpp @@ -0,0 +1,85 @@ +// +// detail/reactive_null_buffers_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_REACTIVE_NULL_BUFFERS_OP_HPP +#define ASIO_DETAIL_REACTIVE_NULL_BUFFERS_OP_HPP + + +#include "asio/detail/config.hpp" +#include "asio/detail/addressof.hpp" +#include "asio/detail/fenced_block.hpp" +#include "asio/detail/handler_alloc_helpers.hpp" +#include "asio/detail/handler_invoke_helpers.hpp" +#include "asio/detail/reactor_op.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename Handler> +class reactive_null_buffers_op : public reactor_op +{ +public: + ASIO_DEFINE_HANDLER_PTR(reactive_null_buffers_op); + + reactive_null_buffers_op(Handler& handler) + : reactor_op(&reactive_null_buffers_op::do_perform, + &reactive_null_buffers_op::do_complete), + handler_(ASIO_MOVE_CAST(Handler)(handler)) + { + } + + static bool do_perform(reactor_op*) + { + return true; + } + + static void do_complete(io_service_impl* owner, operation* base, + const asio::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + reactive_null_buffers_op* o(static_cast<reactive_null_buffers_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((o)); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2<Handler, asio::error_code, std::size_t> + handler(o->handler_, o->ec_, o->bytes_transferred_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + asio_handler_invoke_helpers::invoke(handler, handler.handler_); + ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_REACTIVE_NULL_BUFFERS_OP_HPP diff --git a/asio-1.10.6/include/asio/detail/reactive_socket_accept_op.hpp b/asio-1.10.6/include/asio/detail/reactive_socket_accept_op.hpp new file mode 100644 index 0000000..8f4c609 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/reactive_socket_accept_op.hpp @@ -0,0 +1,133 @@ +// +// detail/reactive_socket_accept_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_REACTIVE_SOCKET_ACCEPT_OP_HPP +#define ASIO_DETAIL_REACTIVE_SOCKET_ACCEPT_OP_HPP + + +#include "asio/detail/config.hpp" +#include "asio/detail/addressof.hpp" +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/buffer_sequence_adapter.hpp" +#include "asio/detail/fenced_block.hpp" +#include "asio/detail/reactor_op.hpp" +#include "asio/detail/socket_holder.hpp" +#include "asio/detail/socket_ops.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename Socket, typename Protocol> +class reactive_socket_accept_op_base : public reactor_op +{ +public: + reactive_socket_accept_op_base(socket_type socket, + socket_ops::state_type state, Socket& peer, const Protocol& protocol, + typename Protocol::endpoint* peer_endpoint, func_type complete_func) + : reactor_op(&reactive_socket_accept_op_base::do_perform, complete_func), + socket_(socket), + state_(state), + peer_(peer), + protocol_(protocol), + peer_endpoint_(peer_endpoint) + { + } + + static bool do_perform(reactor_op* base) + { + reactive_socket_accept_op_base* o( + static_cast<reactive_socket_accept_op_base*>(base)); + + std::size_t addrlen = o->peer_endpoint_ ? o->peer_endpoint_->capacity() : 0; + socket_type new_socket = invalid_socket; + bool result = socket_ops::non_blocking_accept(o->socket_, + o->state_, o->peer_endpoint_ ? o->peer_endpoint_->data() : 0, + o->peer_endpoint_ ? &addrlen : 0, o->ec_, new_socket); + + // On success, assign new connection to peer socket object. + if (new_socket != invalid_socket) + { + socket_holder new_socket_holder(new_socket); + if (o->peer_endpoint_) + o->peer_endpoint_->resize(addrlen); + if (!o->peer_.assign(o->protocol_, new_socket, o->ec_)) + new_socket_holder.release(); + } + + return result; + } + +private: + socket_type socket_; + socket_ops::state_type state_; + Socket& peer_; + Protocol protocol_; + typename Protocol::endpoint* peer_endpoint_; +}; + +template <typename Socket, typename Protocol, typename Handler> +class reactive_socket_accept_op : + public reactive_socket_accept_op_base<Socket, Protocol> +{ +public: + ASIO_DEFINE_HANDLER_PTR(reactive_socket_accept_op); + + reactive_socket_accept_op(socket_type socket, + socket_ops::state_type state, Socket& peer, const Protocol& protocol, + typename Protocol::endpoint* peer_endpoint, Handler& handler) + : reactive_socket_accept_op_base<Socket, Protocol>(socket, state, peer, + protocol, peer_endpoint, &reactive_socket_accept_op::do_complete), + handler_(ASIO_MOVE_CAST(Handler)(handler)) + { + } + + static void do_complete(io_service_impl* owner, operation* base, + const asio::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + reactive_socket_accept_op* o(static_cast<reactive_socket_accept_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((o)); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder1<Handler, asio::error_code> + handler(o->handler_, o->ec_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_)); + asio_handler_invoke_helpers::invoke(handler, handler.handler_); + ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_REACTIVE_SOCKET_ACCEPT_OP_HPP diff --git a/asio-1.10.6/include/asio/detail/reactive_socket_connect_op.hpp b/asio-1.10.6/include/asio/detail/reactive_socket_connect_op.hpp new file mode 100644 index 0000000..ccc94eb --- /dev/null +++ b/asio-1.10.6/include/asio/detail/reactive_socket_connect_op.hpp @@ -0,0 +1,103 @@ +// +// detail/reactive_socket_connect_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_REACTIVE_SOCKET_CONNECT_OP_HPP +#define ASIO_DETAIL_REACTIVE_SOCKET_CONNECT_OP_HPP + + +#include "asio/detail/config.hpp" +#include "asio/detail/addressof.hpp" +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/buffer_sequence_adapter.hpp" +#include "asio/detail/fenced_block.hpp" +#include "asio/detail/reactor_op.hpp" +#include "asio/detail/socket_ops.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class reactive_socket_connect_op_base : public reactor_op +{ +public: + reactive_socket_connect_op_base(socket_type socket, func_type complete_func) + : reactor_op(&reactive_socket_connect_op_base::do_perform, complete_func), + socket_(socket) + { + } + + static bool do_perform(reactor_op* base) + { + reactive_socket_connect_op_base* o( + static_cast<reactive_socket_connect_op_base*>(base)); + + return socket_ops::non_blocking_connect(o->socket_, o->ec_); + } + +private: + socket_type socket_; +}; + +template <typename Handler> +class reactive_socket_connect_op : public reactive_socket_connect_op_base +{ +public: + ASIO_DEFINE_HANDLER_PTR(reactive_socket_connect_op); + + reactive_socket_connect_op(socket_type socket, Handler& handler) + : reactive_socket_connect_op_base(socket, + &reactive_socket_connect_op::do_complete), + handler_(ASIO_MOVE_CAST(Handler)(handler)) + { + } + + static void do_complete(io_service_impl* owner, operation* base, + const asio::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + reactive_socket_connect_op* o + (static_cast<reactive_socket_connect_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((o)); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder1<Handler, asio::error_code> + handler(o->handler_, o->ec_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_)); + asio_handler_invoke_helpers::invoke(handler, handler); + ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_REACTIVE_SOCKET_CONNECT_OP_HPP diff --git a/asio-1.10.6/include/asio/detail/reactive_socket_recv_op.hpp b/asio-1.10.6/include/asio/detail/reactive_socket_recv_op.hpp new file mode 100644 index 0000000..f49aae0 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/reactive_socket_recv_op.hpp @@ -0,0 +1,120 @@ +// +// detail/reactive_socket_recv_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_HPP +#define ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_HPP + + +#include "asio/detail/config.hpp" +#include "asio/detail/addressof.hpp" +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/buffer_sequence_adapter.hpp" +#include "asio/detail/fenced_block.hpp" +#include "asio/detail/reactor_op.hpp" +#include "asio/detail/socket_ops.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename MutableBufferSequence> +class reactive_socket_recv_op_base : public reactor_op +{ +public: + reactive_socket_recv_op_base(socket_type socket, + socket_ops::state_type state, const MutableBufferSequence& buffers, + socket_base::message_flags flags, func_type complete_func) + : reactor_op(&reactive_socket_recv_op_base::do_perform, complete_func), + socket_(socket), + state_(state), + buffers_(buffers), + flags_(flags) + { + } + + static bool do_perform(reactor_op* base) + { + reactive_socket_recv_op_base* o( + static_cast<reactive_socket_recv_op_base*>(base)); + + buffer_sequence_adapter<asio::mutable_buffer, + MutableBufferSequence> bufs(o->buffers_); + + return socket_ops::non_blocking_recv(o->socket_, + bufs.buffers(), bufs.count(), o->flags_, + (o->state_ & socket_ops::stream_oriented) != 0, + o->ec_, o->bytes_transferred_); + } + +private: + socket_type socket_; + socket_ops::state_type state_; + MutableBufferSequence buffers_; + socket_base::message_flags flags_; +}; + +template <typename MutableBufferSequence, typename Handler> +class reactive_socket_recv_op : + public reactive_socket_recv_op_base<MutableBufferSequence> +{ +public: + ASIO_DEFINE_HANDLER_PTR(reactive_socket_recv_op); + + reactive_socket_recv_op(socket_type socket, + socket_ops::state_type state, const MutableBufferSequence& buffers, + socket_base::message_flags flags, Handler& handler) + : reactive_socket_recv_op_base<MutableBufferSequence>(socket, state, + buffers, flags, &reactive_socket_recv_op::do_complete), + handler_(ASIO_MOVE_CAST(Handler)(handler)) + { + } + + static void do_complete(io_service_impl* owner, operation* base, + const asio::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + reactive_socket_recv_op* o(static_cast<reactive_socket_recv_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((o)); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2<Handler, asio::error_code, std::size_t> + handler(o->handler_, o->ec_, o->bytes_transferred_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + asio_handler_invoke_helpers::invoke(handler, handler.handler_); + ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_HPP diff --git a/asio-1.10.6/include/asio/detail/reactive_socket_recvfrom_op.hpp b/asio-1.10.6/include/asio/detail/reactive_socket_recvfrom_op.hpp new file mode 100644 index 0000000..0b06619 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/reactive_socket_recvfrom_op.hpp @@ -0,0 +1,130 @@ +// +// detail/reactive_socket_recvfrom_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_HPP +#define ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_HPP + + +#include "asio/detail/config.hpp" +#include "asio/detail/addressof.hpp" +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/buffer_sequence_adapter.hpp" +#include "asio/detail/fenced_block.hpp" +#include "asio/detail/reactor_op.hpp" +#include "asio/detail/socket_ops.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename MutableBufferSequence, typename Endpoint> +class reactive_socket_recvfrom_op_base : public reactor_op +{ +public: + reactive_socket_recvfrom_op_base(socket_type socket, int protocol_type, + const MutableBufferSequence& buffers, Endpoint& endpoint, + socket_base::message_flags flags, func_type complete_func) + : reactor_op(&reactive_socket_recvfrom_op_base::do_perform, complete_func), + socket_(socket), + protocol_type_(protocol_type), + buffers_(buffers), + sender_endpoint_(endpoint), + flags_(flags) + { + } + + static bool do_perform(reactor_op* base) + { + reactive_socket_recvfrom_op_base* o( + static_cast<reactive_socket_recvfrom_op_base*>(base)); + + buffer_sequence_adapter<asio::mutable_buffer, + MutableBufferSequence> bufs(o->buffers_); + + std::size_t addr_len = o->sender_endpoint_.capacity(); + bool result = socket_ops::non_blocking_recvfrom(o->socket_, + bufs.buffers(), bufs.count(), o->flags_, + o->sender_endpoint_.data(), &addr_len, + o->ec_, o->bytes_transferred_); + + if (result && !o->ec_) + o->sender_endpoint_.resize(addr_len); + + return result; + } + +private: + socket_type socket_; + int protocol_type_; + MutableBufferSequence buffers_; + Endpoint& sender_endpoint_; + socket_base::message_flags flags_; +}; + +template <typename MutableBufferSequence, typename Endpoint, typename Handler> +class reactive_socket_recvfrom_op : + public reactive_socket_recvfrom_op_base<MutableBufferSequence, Endpoint> +{ +public: + ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvfrom_op); + + reactive_socket_recvfrom_op(socket_type socket, int protocol_type, + const MutableBufferSequence& buffers, Endpoint& endpoint, + socket_base::message_flags flags, Handler& handler) + : reactive_socket_recvfrom_op_base<MutableBufferSequence, Endpoint>( + socket, protocol_type, buffers, endpoint, flags, + &reactive_socket_recvfrom_op::do_complete), + handler_(ASIO_MOVE_CAST(Handler)(handler)) + { + } + + static void do_complete(io_service_impl* owner, operation* base, + const asio::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + reactive_socket_recvfrom_op* o( + static_cast<reactive_socket_recvfrom_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((o)); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2<Handler, asio::error_code, std::size_t> + handler(o->handler_, o->ec_, o->bytes_transferred_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + asio_handler_invoke_helpers::invoke(handler, handler.handler_); + ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_HPP diff --git a/asio-1.10.6/include/asio/detail/reactive_socket_recvmsg_op.hpp b/asio-1.10.6/include/asio/detail/reactive_socket_recvmsg_op.hpp new file mode 100644 index 0000000..cd30b47 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/reactive_socket_recvmsg_op.hpp @@ -0,0 +1,122 @@ +// +// detail/reactive_socket_recvmsg_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_HPP +#define ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_HPP + + +#include "asio/detail/config.hpp" +#include "asio/detail/addressof.hpp" +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/buffer_sequence_adapter.hpp" +#include "asio/detail/fenced_block.hpp" +#include "asio/detail/reactor_op.hpp" +#include "asio/detail/socket_ops.hpp" +#include "asio/socket_base.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename MutableBufferSequence> +class reactive_socket_recvmsg_op_base : public reactor_op +{ +public: + reactive_socket_recvmsg_op_base(socket_type socket, + const MutableBufferSequence& buffers, socket_base::message_flags in_flags, + socket_base::message_flags& out_flags, func_type complete_func) + : reactor_op(&reactive_socket_recvmsg_op_base::do_perform, complete_func), + socket_(socket), + buffers_(buffers), + in_flags_(in_flags), + out_flags_(out_flags) + { + } + + static bool do_perform(reactor_op* base) + { + reactive_socket_recvmsg_op_base* o( + static_cast<reactive_socket_recvmsg_op_base*>(base)); + + buffer_sequence_adapter<asio::mutable_buffer, + MutableBufferSequence> bufs(o->buffers_); + + return socket_ops::non_blocking_recvmsg(o->socket_, + bufs.buffers(), bufs.count(), + o->in_flags_, o->out_flags_, + o->ec_, o->bytes_transferred_); + } + +private: + socket_type socket_; + MutableBufferSequence buffers_; + socket_base::message_flags in_flags_; + socket_base::message_flags& out_flags_; +}; + +template <typename MutableBufferSequence, typename Handler> +class reactive_socket_recvmsg_op : + public reactive_socket_recvmsg_op_base<MutableBufferSequence> +{ +public: + ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvmsg_op); + + reactive_socket_recvmsg_op(socket_type socket, + const MutableBufferSequence& buffers, socket_base::message_flags in_flags, + socket_base::message_flags& out_flags, Handler& handler) + : reactive_socket_recvmsg_op_base<MutableBufferSequence>(socket, buffers, + in_flags, out_flags, &reactive_socket_recvmsg_op::do_complete), + handler_(ASIO_MOVE_CAST(Handler)(handler)) + { + } + + static void do_complete(io_service_impl* owner, operation* base, + const asio::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + reactive_socket_recvmsg_op* o( + static_cast<reactive_socket_recvmsg_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((o)); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2<Handler, asio::error_code, std::size_t> + handler(o->handler_, o->ec_, o->bytes_transferred_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + asio_handler_invoke_helpers::invoke(handler, handler.handler_); + ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_HPP diff --git a/asio-1.10.6/include/asio/detail/reactive_socket_send_op.hpp b/asio-1.10.6/include/asio/detail/reactive_socket_send_op.hpp new file mode 100644 index 0000000..28cbf51 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/reactive_socket_send_op.hpp @@ -0,0 +1,117 @@ +// +// detail/reactive_socket_send_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_REACTIVE_SOCKET_SEND_OP_HPP +#define ASIO_DETAIL_REACTIVE_SOCKET_SEND_OP_HPP + + +#include "asio/detail/config.hpp" +#include "asio/detail/addressof.hpp" +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/buffer_sequence_adapter.hpp" +#include "asio/detail/fenced_block.hpp" +#include "asio/detail/reactor_op.hpp" +#include "asio/detail/socket_ops.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename ConstBufferSequence> +class reactive_socket_send_op_base : public reactor_op +{ +public: + reactive_socket_send_op_base(socket_type socket, + const ConstBufferSequence& buffers, + socket_base::message_flags flags, func_type complete_func) + : reactor_op(&reactive_socket_send_op_base::do_perform, complete_func), + socket_(socket), + buffers_(buffers), + flags_(flags) + { + } + + static bool do_perform(reactor_op* base) + { + reactive_socket_send_op_base* o( + static_cast<reactive_socket_send_op_base*>(base)); + + buffer_sequence_adapter<asio::const_buffer, + ConstBufferSequence> bufs(o->buffers_); + + return socket_ops::non_blocking_send(o->socket_, + bufs.buffers(), bufs.count(), o->flags_, + o->ec_, o->bytes_transferred_); + } + +private: + socket_type socket_; + ConstBufferSequence buffers_; + socket_base::message_flags flags_; +}; + +template <typename ConstBufferSequence, typename Handler> +class reactive_socket_send_op : + public reactive_socket_send_op_base<ConstBufferSequence> +{ +public: + ASIO_DEFINE_HANDLER_PTR(reactive_socket_send_op); + + reactive_socket_send_op(socket_type socket, + const ConstBufferSequence& buffers, + socket_base::message_flags flags, Handler& handler) + : reactive_socket_send_op_base<ConstBufferSequence>(socket, + buffers, flags, &reactive_socket_send_op::do_complete), + handler_(ASIO_MOVE_CAST(Handler)(handler)) + { + } + + static void do_complete(io_service_impl* owner, operation* base, + const asio::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + reactive_socket_send_op* o(static_cast<reactive_socket_send_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((o)); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2<Handler, asio::error_code, std::size_t> + handler(o->handler_, o->ec_, o->bytes_transferred_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + asio_handler_invoke_helpers::invoke(handler, handler.handler_); + ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_REACTIVE_SOCKET_SEND_OP_HPP diff --git a/asio-1.10.6/include/asio/detail/reactive_socket_sendto_op.hpp b/asio-1.10.6/include/asio/detail/reactive_socket_sendto_op.hpp new file mode 100644 index 0000000..7621c71 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/reactive_socket_sendto_op.hpp @@ -0,0 +1,120 @@ +// +// detail/reactive_socket_sendto_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_REACTIVE_SOCKET_SENDTO_OP_HPP +#define ASIO_DETAIL_REACTIVE_SOCKET_SENDTO_OP_HPP + + +#include "asio/detail/config.hpp" +#include "asio/detail/addressof.hpp" +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/buffer_sequence_adapter.hpp" +#include "asio/detail/fenced_block.hpp" +#include "asio/detail/reactor_op.hpp" +#include "asio/detail/socket_ops.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename ConstBufferSequence, typename Endpoint> +class reactive_socket_sendto_op_base : public reactor_op +{ +public: + reactive_socket_sendto_op_base(socket_type socket, + const ConstBufferSequence& buffers, const Endpoint& endpoint, + socket_base::message_flags flags, func_type complete_func) + : reactor_op(&reactive_socket_sendto_op_base::do_perform, complete_func), + socket_(socket), + buffers_(buffers), + destination_(endpoint), + flags_(flags) + { + } + + static bool do_perform(reactor_op* base) + { + reactive_socket_sendto_op_base* o( + static_cast<reactive_socket_sendto_op_base*>(base)); + + buffer_sequence_adapter<asio::const_buffer, + ConstBufferSequence> bufs(o->buffers_); + + return socket_ops::non_blocking_sendto(o->socket_, + bufs.buffers(), bufs.count(), o->flags_, + o->destination_.data(), o->destination_.size(), + o->ec_, o->bytes_transferred_); + } + +private: + socket_type socket_; + ConstBufferSequence buffers_; + Endpoint destination_; + socket_base::message_flags flags_; +}; + +template <typename ConstBufferSequence, typename Endpoint, typename Handler> +class reactive_socket_sendto_op : + public reactive_socket_sendto_op_base<ConstBufferSequence, Endpoint> +{ +public: + ASIO_DEFINE_HANDLER_PTR(reactive_socket_sendto_op); + + reactive_socket_sendto_op(socket_type socket, + const ConstBufferSequence& buffers, const Endpoint& endpoint, + socket_base::message_flags flags, Handler& handler) + : reactive_socket_sendto_op_base<ConstBufferSequence, Endpoint>(socket, + buffers, endpoint, flags, &reactive_socket_sendto_op::do_complete), + handler_(ASIO_MOVE_CAST(Handler)(handler)) + { + } + + static void do_complete(io_service_impl* owner, operation* base, + const asio::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + reactive_socket_sendto_op* o(static_cast<reactive_socket_sendto_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((o)); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2<Handler, asio::error_code, std::size_t> + handler(o->handler_, o->ec_, o->bytes_transferred_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + asio_handler_invoke_helpers::invoke(handler, handler.handler_); + ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_REACTIVE_SOCKET_SENDTO_OP_HPP diff --git a/asio-1.10.6/include/asio/detail/reactive_socket_service.hpp b/asio-1.10.6/include/asio/detail/reactive_socket_service.hpp new file mode 100644 index 0000000..4bfbed2 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/reactive_socket_service.hpp @@ -0,0 +1,452 @@ +// +// detail/reactive_socket_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_HPP +#define ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_HPP + + +#include "asio/detail/config.hpp" + + +#include "asio/buffer.hpp" +#include "asio/error.hpp" +#include "asio/io_service.hpp" +#include "asio/socket_base.hpp" +#include "asio/detail/addressof.hpp" +#include "asio/detail/buffer_sequence_adapter.hpp" +#include "asio/detail/noncopyable.hpp" +#include "asio/detail/reactive_null_buffers_op.hpp" +#include "asio/detail/reactive_socket_accept_op.hpp" +#include "asio/detail/reactive_socket_connect_op.hpp" +#include "asio/detail/reactive_socket_recvfrom_op.hpp" +#include "asio/detail/reactive_socket_sendto_op.hpp" +#include "asio/detail/reactive_socket_service_base.hpp" +#include "asio/detail/reactor.hpp" +#include "asio/detail/reactor_op.hpp" +#include "asio/detail/socket_holder.hpp" +#include "asio/detail/socket_ops.hpp" +#include "asio/detail/socket_types.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename Protocol> +class reactive_socket_service : + public reactive_socket_service_base +{ +public: + // The protocol type. + typedef Protocol protocol_type; + + // The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + // The native type of a socket. + typedef socket_type native_handle_type; + + // The implementation type of the socket. + struct implementation_type : + reactive_socket_service_base::base_implementation_type + { + // Default constructor. + implementation_type() + : protocol_(endpoint_type().protocol()) + { + } + + // The protocol associated with the socket. + protocol_type protocol_; + }; + + // Constructor. + reactive_socket_service(asio::io_service& io_service) + : reactive_socket_service_base(io_service) + { + } + + // Move-construct a new socket implementation. + void move_construct(implementation_type& impl, + implementation_type& other_impl) + { + this->base_move_construct(impl, other_impl); + + impl.protocol_ = other_impl.protocol_; + other_impl.protocol_ = endpoint_type().protocol(); + } + + // Move-assign from another socket implementation. + void move_assign(implementation_type& impl, + reactive_socket_service_base& other_service, + implementation_type& other_impl) + { + this->base_move_assign(impl, other_service, other_impl); + + impl.protocol_ = other_impl.protocol_; + other_impl.protocol_ = endpoint_type().protocol(); + } + + // Move-construct a new socket implementation from another protocol type. + template <typename Protocol1> + void converting_move_construct(implementation_type& impl, + typename reactive_socket_service< + Protocol1>::implementation_type& other_impl) + { + this->base_move_construct(impl, other_impl); + + impl.protocol_ = protocol_type(other_impl.protocol_); + other_impl.protocol_ = typename Protocol1::endpoint().protocol(); + } + + // Open a new socket implementation. + asio::error_code open(implementation_type& impl, + const protocol_type& protocol, asio::error_code& ec) + { + if (!do_open(impl, protocol.family(), + protocol.type(), protocol.protocol(), ec)) + impl.protocol_ = protocol; + return ec; + } + + // Assign a native socket to a socket implementation. + asio::error_code assign(implementation_type& impl, + const protocol_type& protocol, const native_handle_type& native_socket, + asio::error_code& ec) + { + if (!do_assign(impl, protocol.type(), native_socket, ec)) + impl.protocol_ = protocol; + return ec; + } + + // Get the native socket representation. + native_handle_type native_handle(implementation_type& impl) + { + return impl.socket_; + } + + // Bind the socket to the specified local endpoint. + asio::error_code bind(implementation_type& impl, + const endpoint_type& endpoint, asio::error_code& ec) + { + socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec); + return ec; + } + + // Set a socket option. + template <typename Option> + asio::error_code set_option(implementation_type& impl, + const Option& option, asio::error_code& ec) + { + socket_ops::setsockopt(impl.socket_, impl.state_, + option.level(impl.protocol_), option.name(impl.protocol_), + option.data(impl.protocol_), option.size(impl.protocol_), ec); + return ec; + } + + // Set a socket option. + template <typename Option> + asio::error_code get_option(const implementation_type& impl, + Option& option, asio::error_code& ec) const + { + std::size_t size = option.size(impl.protocol_); + socket_ops::getsockopt(impl.socket_, impl.state_, + option.level(impl.protocol_), option.name(impl.protocol_), + option.data(impl.protocol_), &size, ec); + if (!ec) + option.resize(impl.protocol_, size); + return ec; + } + + // Get the local endpoint. + endpoint_type local_endpoint(const implementation_type& impl, + asio::error_code& ec) const + { + endpoint_type endpoint; + std::size_t addr_len = endpoint.capacity(); + if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec)) + return endpoint_type(); + endpoint.resize(addr_len); + return endpoint; + } + + // Get the remote endpoint. + endpoint_type remote_endpoint(const implementation_type& impl, + asio::error_code& ec) const + { + endpoint_type endpoint; + std::size_t addr_len = endpoint.capacity(); + if (socket_ops::getpeername(impl.socket_, + endpoint.data(), &addr_len, false, ec)) + return endpoint_type(); + endpoint.resize(addr_len); + return endpoint; + } + + // Send a datagram to the specified endpoint. Returns the number of bytes + // sent. + template <typename ConstBufferSequence> + size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags, + asio::error_code& ec) + { + buffer_sequence_adapter<asio::const_buffer, + ConstBufferSequence> bufs(buffers); + + return socket_ops::sync_sendto(impl.socket_, impl.state_, + bufs.buffers(), bufs.count(), flags, + destination.data(), destination.size(), ec); + } + + // Wait until data can be sent without blocking. + size_t send_to(implementation_type& impl, const null_buffers&, + const endpoint_type&, socket_base::message_flags, + asio::error_code& ec) + { + // Wait for socket to become ready. + socket_ops::poll_write(impl.socket_, impl.state_, ec); + + return 0; + } + + // Start an asynchronous send. The data being sent must be valid for the + // lifetime of the asynchronous operation. + template <typename ConstBufferSequence, typename Handler> + void async_send_to(implementation_type& impl, + const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags, + Handler& handler) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_socket_sendto_op<ConstBufferSequence, + endpoint_type, Handler> op; + typename op::ptr p = { asio::detail::addressof(handler), + asio_handler_alloc_helpers::allocate( + sizeof(op), handler), 0 }; + p.p = new (p.v) op(impl.socket_, buffers, destination, flags, handler); + + ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_send_to")); + + start_op(impl, reactor::write_op, p.p, is_continuation, true, false); + p.v = p.p = 0; + } + + // Start an asynchronous wait until data can be sent without blocking. + template <typename Handler> + void async_send_to(implementation_type& impl, const null_buffers&, + const endpoint_type&, socket_base::message_flags, Handler& handler) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_null_buffers_op<Handler> op; + typename op::ptr p = { asio::detail::addressof(handler), + asio_handler_alloc_helpers::allocate( + sizeof(op), handler), 0 }; + p.p = new (p.v) op(handler); + + ASIO_HANDLER_CREATION((p.p, "socket", + &impl, "async_send_to(null_buffers)")); + + start_op(impl, reactor::write_op, p.p, is_continuation, false, false); + p.v = p.p = 0; + } + + // Receive a datagram with the endpoint of the sender. Returns the number of + // bytes received. + template <typename MutableBufferSequence> + size_t receive_from(implementation_type& impl, + const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags, + asio::error_code& ec) + { + buffer_sequence_adapter<asio::mutable_buffer, + MutableBufferSequence> bufs(buffers); + + std::size_t addr_len = sender_endpoint.capacity(); + std::size_t bytes_recvd = socket_ops::sync_recvfrom( + impl.socket_, impl.state_, bufs.buffers(), bufs.count(), + flags, sender_endpoint.data(), &addr_len, ec); + + if (!ec) + sender_endpoint.resize(addr_len); + + return bytes_recvd; + } + + // Wait until data can be received without blocking. + size_t receive_from(implementation_type& impl, const null_buffers&, + endpoint_type& sender_endpoint, socket_base::message_flags, + asio::error_code& ec) + { + // Wait for socket to become ready. + socket_ops::poll_read(impl.socket_, impl.state_, ec); + + // Reset endpoint since it can be given no sensible value at this time. + sender_endpoint = endpoint_type(); + + return 0; + } + + // Start an asynchronous receive. The buffer for the data being received and + // the sender_endpoint object must both be valid for the lifetime of the + // asynchronous operation. + template <typename MutableBufferSequence, typename Handler> + void async_receive_from(implementation_type& impl, + const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, + socket_base::message_flags flags, Handler& handler) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_socket_recvfrom_op<MutableBufferSequence, + endpoint_type, Handler> op; + typename op::ptr p = { asio::detail::addressof(handler), + asio_handler_alloc_helpers::allocate( + sizeof(op), handler), 0 }; + int protocol = impl.protocol_.type(); + p.p = new (p.v) op(impl.socket_, protocol, + buffers, sender_endpoint, flags, handler); + + ASIO_HANDLER_CREATION((p.p, "socket", + &impl, "async_receive_from")); + + start_op(impl, + (flags & socket_base::message_out_of_band) + ? reactor::except_op : reactor::read_op, + p.p, is_continuation, true, false); + p.v = p.p = 0; + } + + // Wait until data can be received without blocking. + template <typename Handler> + void async_receive_from(implementation_type& impl, + const null_buffers&, endpoint_type& sender_endpoint, + socket_base::message_flags flags, Handler& handler) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_null_buffers_op<Handler> op; + typename op::ptr p = { asio::detail::addressof(handler), + asio_handler_alloc_helpers::allocate( + sizeof(op), handler), 0 }; + p.p = new (p.v) op(handler); + + ASIO_HANDLER_CREATION((p.p, "socket", + &impl, "async_receive_from(null_buffers)")); + + // Reset endpoint since it can be given no sensible value at this time. + sender_endpoint = endpoint_type(); + + start_op(impl, + (flags & socket_base::message_out_of_band) + ? reactor::except_op : reactor::read_op, + p.p, is_continuation, false, false); + p.v = p.p = 0; + } + + // Accept a new connection. + template <typename Socket> + asio::error_code accept(implementation_type& impl, + Socket& peer, endpoint_type* peer_endpoint, asio::error_code& ec) + { + // We cannot accept a socket that is already open. + if (peer.is_open()) + { + ec = asio::error::already_open; + return ec; + } + + std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0; + socket_holder new_socket(socket_ops::sync_accept(impl.socket_, + impl.state_, peer_endpoint ? peer_endpoint->data() : 0, + peer_endpoint ? &addr_len : 0, ec)); + + // On success, assign new connection to peer socket object. + if (new_socket.get() != invalid_socket) + { + if (peer_endpoint) + peer_endpoint->resize(addr_len); + if (!peer.assign(impl.protocol_, new_socket.get(), ec)) + new_socket.release(); + } + + return ec; + } + + // Start an asynchronous accept. The peer and peer_endpoint objects + // must be valid until the accept's handler is invoked. + template <typename Socket, typename Handler> + void async_accept(implementation_type& impl, Socket& peer, + endpoint_type* peer_endpoint, Handler& handler) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_socket_accept_op<Socket, Protocol, Handler> op; + typename op::ptr p = { asio::detail::addressof(handler), + asio_handler_alloc_helpers::allocate( + sizeof(op), handler), 0 }; + p.p = new (p.v) op(impl.socket_, impl.state_, peer, + impl.protocol_, peer_endpoint, handler); + + ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_accept")); + + start_accept_op(impl, p.p, is_continuation, peer.is_open()); + p.v = p.p = 0; + } + + // Connect the socket to the specified endpoint. + asio::error_code connect(implementation_type& impl, + const endpoint_type& peer_endpoint, asio::error_code& ec) + { + socket_ops::sync_connect(impl.socket_, + peer_endpoint.data(), peer_endpoint.size(), ec); + return ec; + } + + // Start an asynchronous connect. + template <typename Handler> + void async_connect(implementation_type& impl, + const endpoint_type& peer_endpoint, Handler& handler) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_socket_connect_op<Handler> op; + typename op::ptr p = { asio::detail::addressof(handler), + asio_handler_alloc_helpers::allocate( + sizeof(op), handler), 0 }; + p.p = new (p.v) op(impl.socket_, handler); + + ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_connect")); + + start_connect_op(impl, p.p, is_continuation, + peer_endpoint.data(), peer_endpoint.size()); + p.v = p.p = 0; + } +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + + +#endif // ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_HPP diff --git a/asio-1.10.6/include/asio/detail/reactive_socket_service_base.hpp b/asio-1.10.6/include/asio/detail/reactive_socket_service_base.hpp new file mode 100644 index 0000000..957d975 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/reactive_socket_service_base.hpp @@ -0,0 +1,442 @@ +// +// detail/reactive_socket_service_base.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_HPP +#define ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_HPP + + +#include "asio/detail/config.hpp" + + +#include "asio/buffer.hpp" +#include "asio/error.hpp" +#include "asio/io_service.hpp" +#include "asio/socket_base.hpp" +#include "asio/detail/addressof.hpp" +#include "asio/detail/buffer_sequence_adapter.hpp" +#include "asio/detail/reactive_null_buffers_op.hpp" +#include "asio/detail/reactive_socket_recv_op.hpp" +#include "asio/detail/reactive_socket_recvmsg_op.hpp" +#include "asio/detail/reactive_socket_send_op.hpp" +#include "asio/detail/reactor.hpp" +#include "asio/detail/reactor_op.hpp" +#include "asio/detail/socket_holder.hpp" +#include "asio/detail/socket_ops.hpp" +#include "asio/detail/socket_types.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class reactive_socket_service_base +{ +public: + // The native type of a socket. + typedef socket_type native_handle_type; + + // The implementation type of the socket. + struct base_implementation_type + { + // The native socket representation. + socket_type socket_; + + // The current state of the socket. + socket_ops::state_type state_; + + // Per-descriptor data used by the reactor. + reactor::per_descriptor_data reactor_data_; + }; + + // Constructor. + ASIO_DECL reactive_socket_service_base( + asio::io_service& io_service); + + // Destroy all user-defined handler objects owned by the service. + ASIO_DECL void shutdown_service(); + + // Construct a new socket implementation. + ASIO_DECL void construct(base_implementation_type& impl); + + // Move-construct a new socket implementation. + ASIO_DECL void base_move_construct(base_implementation_type& impl, + base_implementation_type& other_impl); + + // Move-assign from another socket implementation. + ASIO_DECL void base_move_assign(base_implementation_type& impl, + reactive_socket_service_base& other_service, + base_implementation_type& other_impl); + + // Destroy a socket implementation. + ASIO_DECL void destroy(base_implementation_type& impl); + + // Determine whether the socket is open. + bool is_open(const base_implementation_type& impl) const + { + return impl.socket_ != invalid_socket; + } + + // Destroy a socket implementation. + ASIO_DECL asio::error_code close( + base_implementation_type& impl, asio::error_code& ec); + + // Get the native socket representation. + native_handle_type native_handle(base_implementation_type& impl) + { + return impl.socket_; + } + + // Cancel all operations associated with the socket. + ASIO_DECL asio::error_code cancel( + base_implementation_type& impl, asio::error_code& ec); + + // Determine whether the socket is at the out-of-band data mark. + bool at_mark(const base_implementation_type& impl, + asio::error_code& ec) const + { + return socket_ops::sockatmark(impl.socket_, ec); + } + + // Determine the number of bytes available for reading. + std::size_t available(const base_implementation_type& impl, + asio::error_code& ec) const + { + return socket_ops::available(impl.socket_, ec); + } + + // Place the socket into the state where it will listen for new connections. + asio::error_code listen(base_implementation_type& impl, + int backlog, asio::error_code& ec) + { + socket_ops::listen(impl.socket_, backlog, ec); + return ec; + } + + // Perform an IO control command on the socket. + template <typename IO_Control_Command> + asio::error_code io_control(base_implementation_type& impl, + IO_Control_Command& command, asio::error_code& ec) + { + socket_ops::ioctl(impl.socket_, impl.state_, command.name(), + static_cast<ioctl_arg_type*>(command.data()), ec); + return ec; + } + + // Gets the non-blocking mode of the socket. + bool non_blocking(const base_implementation_type& impl) const + { + return (impl.state_ & socket_ops::user_set_non_blocking) != 0; + } + + // Sets the non-blocking mode of the socket. + asio::error_code non_blocking(base_implementation_type& impl, + bool mode, asio::error_code& ec) + { + socket_ops::set_user_non_blocking(impl.socket_, impl.state_, mode, ec); + return ec; + } + + // Gets the non-blocking mode of the native socket implementation. + bool native_non_blocking(const base_implementation_type& impl) const + { + return (impl.state_ & socket_ops::internal_non_blocking) != 0; + } + + // Sets the non-blocking mode of the native socket implementation. + asio::error_code native_non_blocking(base_implementation_type& impl, + bool mode, asio::error_code& ec) + { + socket_ops::set_internal_non_blocking(impl.socket_, impl.state_, mode, ec); + return ec; + } + + // Disable sends or receives on the socket. + asio::error_code shutdown(base_implementation_type& impl, + socket_base::shutdown_type what, asio::error_code& ec) + { + socket_ops::shutdown(impl.socket_, what, ec); + return ec; + } + + // Send the given data to the peer. + template <typename ConstBufferSequence> + size_t send(base_implementation_type& impl, + const ConstBufferSequence& buffers, + socket_base::message_flags flags, asio::error_code& ec) + { + buffer_sequence_adapter<asio::const_buffer, + ConstBufferSequence> bufs(buffers); + + return socket_ops::sync_send(impl.socket_, impl.state_, + bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec); + } + + // Wait until data can be sent without blocking. + size_t send(base_implementation_type& impl, const null_buffers&, + socket_base::message_flags, asio::error_code& ec) + { + // Wait for socket to become ready. + socket_ops::poll_write(impl.socket_, impl.state_, ec); + + return 0; + } + + // Start an asynchronous send. The data being sent must be valid for the + // lifetime of the asynchronous operation. + template <typename ConstBufferSequence, typename Handler> + void async_send(base_implementation_type& impl, + const ConstBufferSequence& buffers, + socket_base::message_flags flags, Handler& handler) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_socket_send_op<ConstBufferSequence, Handler> op; + typename op::ptr p = { asio::detail::addressof(handler), + asio_handler_alloc_helpers::allocate( + sizeof(op), handler), 0 }; + p.p = new (p.v) op(impl.socket_, buffers, flags, handler); + + ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_send")); + + start_op(impl, reactor::write_op, p.p, is_continuation, true, + ((impl.state_ & socket_ops::stream_oriented) + && buffer_sequence_adapter<asio::const_buffer, + ConstBufferSequence>::all_empty(buffers))); + p.v = p.p = 0; + } + + // Start an asynchronous wait until data can be sent without blocking. + template <typename Handler> + void async_send(base_implementation_type& impl, const null_buffers&, + socket_base::message_flags, Handler& handler) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_null_buffers_op<Handler> op; + typename op::ptr p = { asio::detail::addressof(handler), + asio_handler_alloc_helpers::allocate( + sizeof(op), handler), 0 }; + p.p = new (p.v) op(handler); + + ASIO_HANDLER_CREATION((p.p, "socket", + &impl, "async_send(null_buffers)")); + + start_op(impl, reactor::write_op, p.p, is_continuation, false, false); + p.v = p.p = 0; + } + + // Receive some data from the peer. Returns the number of bytes received. + template <typename MutableBufferSequence> + size_t receive(base_implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, asio::error_code& ec) + { + buffer_sequence_adapter<asio::mutable_buffer, + MutableBufferSequence> bufs(buffers); + + return socket_ops::sync_recv(impl.socket_, impl.state_, + bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec); + } + + // Wait until data can be received without blocking. + size_t receive(base_implementation_type& impl, const null_buffers&, + socket_base::message_flags, asio::error_code& ec) + { + // Wait for socket to become ready. + socket_ops::poll_read(impl.socket_, impl.state_, ec); + + return 0; + } + + // Start an asynchronous receive. The buffer for the data being received + // must be valid for the lifetime of the asynchronous operation. + template <typename MutableBufferSequence, typename Handler> + void async_receive(base_implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, Handler& handler) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_socket_recv_op<MutableBufferSequence, Handler> op; + typename op::ptr p = { asio::detail::addressof(handler), + asio_handler_alloc_helpers::allocate( + sizeof(op), handler), 0 }; + p.p = new (p.v) op(impl.socket_, impl.state_, buffers, flags, handler); + + ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_receive")); + + start_op(impl, + (flags & socket_base::message_out_of_band) + ? reactor::except_op : reactor::read_op, + p.p, is_continuation, + (flags & socket_base::message_out_of_band) == 0, + ((impl.state_ & socket_ops::stream_oriented) + && buffer_sequence_adapter<asio::mutable_buffer, + MutableBufferSequence>::all_empty(buffers))); + p.v = p.p = 0; + } + + // Wait until data can be received without blocking. + template <typename Handler> + void async_receive(base_implementation_type& impl, const null_buffers&, + socket_base::message_flags flags, Handler& handler) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_null_buffers_op<Handler> op; + typename op::ptr p = { asio::detail::addressof(handler), + asio_handler_alloc_helpers::allocate( + sizeof(op), handler), 0 }; + p.p = new (p.v) op(handler); + + ASIO_HANDLER_CREATION((p.p, "socket", + &impl, "async_receive(null_buffers)")); + + start_op(impl, + (flags & socket_base::message_out_of_band) + ? reactor::except_op : reactor::read_op, + p.p, is_continuation, false, false); + p.v = p.p = 0; + } + + // Receive some data with associated flags. Returns the number of bytes + // received. + template <typename MutableBufferSequence> + size_t receive_with_flags(base_implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags in_flags, + socket_base::message_flags& out_flags, asio::error_code& ec) + { + buffer_sequence_adapter<asio::mutable_buffer, + MutableBufferSequence> bufs(buffers); + + return socket_ops::sync_recvmsg(impl.socket_, impl.state_, + bufs.buffers(), bufs.count(), in_flags, out_flags, ec); + } + + // Wait until data can be received without blocking. + size_t receive_with_flags(base_implementation_type& impl, + const null_buffers&, socket_base::message_flags, + socket_base::message_flags& out_flags, asio::error_code& ec) + { + // Wait for socket to become ready. + socket_ops::poll_read(impl.socket_, impl.state_, ec); + + // Clear out_flags, since we cannot give it any other sensible value when + // performing a null_buffers operation. + out_flags = 0; + + return 0; + } + + // Start an asynchronous receive. The buffer for the data being received + // must be valid for the lifetime of the asynchronous operation. + template <typename MutableBufferSequence, typename Handler> + void async_receive_with_flags(base_implementation_type& impl, + const MutableBufferSequence& buffers, socket_base::message_flags in_flags, + socket_base::message_flags& out_flags, Handler& handler) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_socket_recvmsg_op<MutableBufferSequence, Handler> op; + typename op::ptr p = { asio::detail::addressof(handler), + asio_handler_alloc_helpers::allocate( + sizeof(op), handler), 0 }; + p.p = new (p.v) op(impl.socket_, buffers, in_flags, out_flags, handler); + + ASIO_HANDLER_CREATION((p.p, "socket", + &impl, "async_receive_with_flags")); + + start_op(impl, + (in_flags & socket_base::message_out_of_band) + ? reactor::except_op : reactor::read_op, + p.p, is_continuation, + (in_flags & socket_base::message_out_of_band) == 0, false); + p.v = p.p = 0; + } + + // Wait until data can be received without blocking. + template <typename Handler> + void async_receive_with_flags(base_implementation_type& impl, + const null_buffers&, socket_base::message_flags in_flags, + socket_base::message_flags& out_flags, Handler& handler) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_null_buffers_op<Handler> op; + typename op::ptr p = { asio::detail::addressof(handler), + asio_handler_alloc_helpers::allocate( + sizeof(op), handler), 0 }; + p.p = new (p.v) op(handler); + + ASIO_HANDLER_CREATION((p.p, "socket", &impl, + "async_receive_with_flags(null_buffers)")); + + // Clear out_flags, since we cannot give it any other sensible value when + // performing a null_buffers operation. + out_flags = 0; + + start_op(impl, + (in_flags & socket_base::message_out_of_band) + ? reactor::except_op : reactor::read_op, + p.p, is_continuation, false, false); + p.v = p.p = 0; + } + +protected: + // Open a new socket implementation. + ASIO_DECL asio::error_code do_open( + base_implementation_type& impl, int af, + int type, int protocol, asio::error_code& ec); + + // Assign a native socket to a socket implementation. + ASIO_DECL asio::error_code do_assign( + base_implementation_type& impl, int type, + const native_handle_type& native_socket, asio::error_code& ec); + + // Start the asynchronous read or write operation. + ASIO_DECL void start_op(base_implementation_type& impl, int op_type, + reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop); + + // Start the asynchronous accept operation. + ASIO_DECL void start_accept_op(base_implementation_type& impl, + reactor_op* op, bool is_continuation, bool peer_is_open); + + // Start the asynchronous connect operation. + ASIO_DECL void start_connect_op(base_implementation_type& impl, + reactor_op* op, bool is_continuation, + const socket_addr_type* addr, size_t addrlen); + + // The selector that performs event demultiplexing for the service. + reactor& reactor_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +# include "asio/detail/impl/reactive_socket_service_base.ipp" + + // && !defined(ASIO_WINDOWS_RUNTIME) + +#endif // ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_HPP diff --git a/asio-1.10.6/include/asio/detail/reactor.hpp b/asio-1.10.6/include/asio/detail/reactor.hpp new file mode 100644 index 0000000..a9499ab --- /dev/null +++ b/asio-1.10.6/include/asio/detail/reactor.hpp @@ -0,0 +1,25 @@ +// +// detail/reactor.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_REACTOR_HPP +#define ASIO_DETAIL_REACTOR_HPP + + +#include "asio/detail/reactor_fwd.hpp" + +#if defined(ASIO_HAS_EPOLL) +# include "asio/detail/epoll_reactor.hpp" +#elif defined(ASIO_HAS_DEV_POLL) +# include "asio/detail/dev_poll_reactor.hpp" +#else +# include "asio/detail/select_reactor.hpp" +#endif + +#endif // ASIO_DETAIL_REACTOR_HPP diff --git a/asio-1.10.6/include/asio/detail/reactor_fwd.hpp b/asio-1.10.6/include/asio/detail/reactor_fwd.hpp new file mode 100644 index 0000000..d9f8a24 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/reactor_fwd.hpp @@ -0,0 +1,31 @@ +// +// detail/reactor_fwd.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_REACTOR_FWD_HPP +#define ASIO_DETAIL_REACTOR_FWD_HPP + + +#include "asio/detail/config.hpp" + +namespace asio { +namespace detail { + +#if defined(ASIO_HAS_EPOLL) +typedef class epoll_reactor reactor; +#elif defined(ASIO_HAS_DEV_POLL) +typedef class dev_poll_reactor reactor; +#else +typedef class select_reactor reactor; +#endif + +} // namespace detail +} // namespace asio + +#endif // ASIO_DETAIL_REACTOR_FWD_HPP diff --git a/asio-1.10.6/include/asio/detail/reactor_op.hpp b/asio-1.10.6/include/asio/detail/reactor_op.hpp new file mode 100644 index 0000000..5e0ea9b --- /dev/null +++ b/asio-1.10.6/include/asio/detail/reactor_op.hpp @@ -0,0 +1,58 @@ +// +// detail/reactor_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_REACTOR_OP_HPP +#define ASIO_DETAIL_REACTOR_OP_HPP + + +#include "asio/detail/config.hpp" +#include "asio/detail/operation.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class reactor_op + : public operation +{ +public: + // The error code to be passed to the completion handler. + asio::error_code ec_; + + // The number of bytes transferred, to be passed to the completion handler. + std::size_t bytes_transferred_; + + // Perform the operation. Returns true if it is finished. + bool perform() + { + return perform_func_(this); + } + +protected: + typedef bool (*perform_func_type)(reactor_op*); + + reactor_op(perform_func_type perform_func, func_type complete_func) + : operation(complete_func), + bytes_transferred_(0), + perform_func_(perform_func) + { + } + +private: + perform_func_type perform_func_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_REACTOR_OP_HPP diff --git a/asio-1.10.6/include/asio/detail/reactor_op_queue.hpp b/asio-1.10.6/include/asio/detail/reactor_op_queue.hpp new file mode 100644 index 0000000..3038cd4 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/reactor_op_queue.hpp @@ -0,0 +1,165 @@ +// +// detail/reactor_op_queue.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_REACTOR_OP_QUEUE_HPP +#define ASIO_DETAIL_REACTOR_OP_QUEUE_HPP + + +#include "asio/detail/config.hpp" +#include "asio/detail/hash_map.hpp" +#include "asio/detail/noncopyable.hpp" +#include "asio/detail/op_queue.hpp" +#include "asio/detail/reactor_op.hpp" +#include "asio/error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename Descriptor> +class reactor_op_queue + : private noncopyable +{ +public: + typedef Descriptor key_type; + + struct mapped_type : op_queue<reactor_op> + { + mapped_type() {} + mapped_type(const mapped_type&) {} + void operator=(const mapped_type&) {} + }; + + typedef typename hash_map<key_type, mapped_type>::value_type value_type; + typedef typename hash_map<key_type, mapped_type>::iterator iterator; + + // Constructor. + reactor_op_queue() + : operations_() + { + } + + // Obtain iterators to all registered descriptors. + iterator begin() { return operations_.begin(); } + iterator end() { return operations_.end(); } + + // Add a new operation to the queue. Returns true if this is the only + // operation for the given descriptor, in which case the reactor's event + // demultiplexing function call may need to be interrupted and restarted. + bool enqueue_operation(Descriptor descriptor, reactor_op* op) + { + std::pair<iterator, bool> entry = + operations_.insert(value_type(descriptor, mapped_type())); + entry.first->second.push(op); + return entry.second; + } + + // Cancel all operations associated with the descriptor identified by the + // supplied iterator. Any operations pending for the descriptor will be + // cancelled. Returns true if any operations were cancelled, in which case + // the reactor's event demultiplexing function may need to be interrupted and + // restarted. + bool cancel_operations(iterator i, op_queue<operation>& ops, + const asio::error_code& ec = + asio::error::operation_aborted) + { + if (i != operations_.end()) + { + while (reactor_op* op = i->second.front()) + { + op->ec_ = ec; + i->second.pop(); + ops.push(op); + } + operations_.erase(i); + return true; + } + + return false; + } + + // Cancel all operations associated with the descriptor. Any operations + // pending for the descriptor will be cancelled. Returns true if any + // operations were cancelled, in which case the reactor's event + // demultiplexing function may need to be interrupted and restarted. + bool cancel_operations(Descriptor descriptor, op_queue<operation>& ops, + const asio::error_code& ec = + asio::error::operation_aborted) + { + return this->cancel_operations(operations_.find(descriptor), ops, ec); + } + + // Whether there are no operations in the queue. + bool empty() const + { + return operations_.empty(); + } + + // Determine whether there are any operations associated with the descriptor. + bool has_operation(Descriptor descriptor) const + { + return operations_.find(descriptor) != operations_.end(); + } + + // Perform the operations corresponding to the descriptor identified by the + // supplied iterator. Returns true if there are still unfinished operations + // queued for the descriptor. + bool perform_operations(iterator i, op_queue<operation>& ops) + { + if (i != operations_.end()) + { + while (reactor_op* op = i->second.front()) + { + if (op->perform()) + { + i->second.pop(); + ops.push(op); + } + else + { + return true; + } + } + operations_.erase(i); + } + return false; + } + + // Perform the operations corresponding to the descriptor. Returns true if + // there are still unfinished operations queued for the descriptor. + bool perform_operations(Descriptor descriptor, op_queue<operation>& ops) + { + return this->perform_operations(operations_.find(descriptor), ops); + } + + // Get all operations owned by the queue. + void get_all_operations(op_queue<operation>& ops) + { + iterator i = operations_.begin(); + while (i != operations_.end()) + { + iterator op_iter = i++; + ops.push(op_iter->second); + operations_.erase(op_iter); + } + } + +private: + // The operations that are currently executing asynchronously. + hash_map<key_type, mapped_type> operations_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_REACTOR_OP_QUEUE_HPP diff --git a/asio-1.10.6/include/asio/detail/resolve_endpoint_op.hpp b/asio-1.10.6/include/asio/detail/resolve_endpoint_op.hpp new file mode 100644 index 0000000..615d740 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/resolve_endpoint_op.hpp @@ -0,0 +1,118 @@ +// +// detail/resolve_endpoint_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_RESOLVER_ENDPOINT_OP_HPP +#define ASIO_DETAIL_RESOLVER_ENDPOINT_OP_HPP + + +#include "asio/detail/config.hpp" +#include "asio/error.hpp" +#include "asio/io_service.hpp" +#include "asio/ip/basic_resolver_iterator.hpp" +#include "asio/detail/addressof.hpp" +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/fenced_block.hpp" +#include "asio/detail/handler_alloc_helpers.hpp" +#include "asio/detail/handler_invoke_helpers.hpp" +#include "asio/detail/operation.hpp" +#include "asio/detail/socket_ops.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename Protocol, typename Handler> +class resolve_endpoint_op : public operation +{ +public: + ASIO_DEFINE_HANDLER_PTR(resolve_endpoint_op); + + typedef typename Protocol::endpoint endpoint_type; + typedef asio::ip::basic_resolver_iterator<Protocol> iterator_type; + + resolve_endpoint_op(socket_ops::weak_cancel_token_type cancel_token, + const endpoint_type& endpoint, io_service_impl& ios, Handler& handler) + : operation(&resolve_endpoint_op::do_complete), + cancel_token_(cancel_token), + endpoint_(endpoint), + io_service_impl_(ios), + handler_(ASIO_MOVE_CAST(Handler)(handler)) + { + } + + static void do_complete(io_service_impl* owner, operation* base, + const asio::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the operation object. + resolve_endpoint_op* o(static_cast<resolve_endpoint_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + if (owner && owner != &o->io_service_impl_) + { + // The operation is being run on the worker io_service. Time to perform + // the resolver operation. + + // Perform the blocking endpoint resolution operation. + char host_name[NI_MAXHOST]; + char service_name[NI_MAXSERV]; + socket_ops::background_getnameinfo(o->cancel_token_, o->endpoint_.data(), + o->endpoint_.size(), host_name, NI_MAXHOST, service_name, NI_MAXSERV, + o->endpoint_.protocol().type(), o->ec_); + o->iter_ = iterator_type::create(o->endpoint_, host_name, service_name); + + // Pass operation back to main io_service for completion. + o->io_service_impl_.post_deferred_completion(o); + p.v = p.p = 0; + } + else + { + // The operation has been returned to the main io_service. The completion + // handler is ready to be delivered. + + ASIO_HANDLER_COMPLETION((o)); + + // Make a copy of the handler so that the memory can be deallocated + // before the upcall is made. Even if we're not about to make an upcall, + // a sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + detail::binder2<Handler, asio::error_code, iterator_type> + handler(o->handler_, o->ec_, o->iter_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + if (owner) + { + fenced_block b(fenced_block::half); + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, "...")); + asio_handler_invoke_helpers::invoke(handler, handler.handler_); + ASIO_HANDLER_INVOCATION_END; + } + } + } + +private: + socket_ops::weak_cancel_token_type cancel_token_; + endpoint_type endpoint_; + io_service_impl& io_service_impl_; + Handler handler_; + asio::error_code ec_; + iterator_type iter_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_RESOLVER_ENDPOINT_OP_HPP diff --git a/asio-1.10.6/include/asio/detail/resolve_op.hpp b/asio-1.10.6/include/asio/detail/resolve_op.hpp new file mode 100644 index 0000000..f2fbde4 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/resolve_op.hpp @@ -0,0 +1,128 @@ +// +// detail/resolve_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_RESOLVE_OP_HPP +#define ASIO_DETAIL_RESOLVE_OP_HPP + + +#include "asio/detail/config.hpp" +#include "asio/error.hpp" +#include "asio/io_service.hpp" +#include "asio/ip/basic_resolver_iterator.hpp" +#include "asio/ip/basic_resolver_query.hpp" +#include "asio/detail/addressof.hpp" +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/fenced_block.hpp" +#include "asio/detail/handler_alloc_helpers.hpp" +#include "asio/detail/handler_invoke_helpers.hpp" +#include "asio/detail/operation.hpp" +#include "asio/detail/socket_ops.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename Protocol, typename Handler> +class resolve_op : public operation +{ +public: + ASIO_DEFINE_HANDLER_PTR(resolve_op); + + typedef asio::ip::basic_resolver_query<Protocol> query_type; + typedef asio::ip::basic_resolver_iterator<Protocol> iterator_type; + + resolve_op(socket_ops::weak_cancel_token_type cancel_token, + const query_type& query, io_service_impl& ios, Handler& handler) + : operation(&resolve_op::do_complete), + cancel_token_(cancel_token), + query_(query), + io_service_impl_(ios), + handler_(ASIO_MOVE_CAST(Handler)(handler)), + addrinfo_(0) + { + } + + ~resolve_op() + { + if (addrinfo_) + socket_ops::freeaddrinfo(addrinfo_); + } + + static void do_complete(io_service_impl* owner, operation* base, + const asio::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the operation object. + resolve_op* o(static_cast<resolve_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + if (owner && owner != &o->io_service_impl_) + { + // The operation is being run on the worker io_service. Time to perform + // the resolver operation. + + // Perform the blocking host resolution operation. + socket_ops::background_getaddrinfo(o->cancel_token_, + o->query_.host_name().c_str(), o->query_.service_name().c_str(), + o->query_.hints(), &o->addrinfo_, o->ec_); + + // Pass operation back to main io_service for completion. + o->io_service_impl_.post_deferred_completion(o); + p.v = p.p = 0; + } + else + { + // The operation has been returned to the main io_service. The completion + // handler is ready to be delivered. + + ASIO_HANDLER_COMPLETION((o)); + + // Make a copy of the handler so that the memory can be deallocated + // before the upcall is made. Even if we're not about to make an upcall, + // a sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + detail::binder2<Handler, asio::error_code, iterator_type> + handler(o->handler_, o->ec_, iterator_type()); + p.h = asio::detail::addressof(handler.handler_); + if (o->addrinfo_) + { + handler.arg2_ = iterator_type::create(o->addrinfo_, + o->query_.host_name(), o->query_.service_name()); + } + p.reset(); + + if (owner) + { + fenced_block b(fenced_block::half); + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, "...")); + asio_handler_invoke_helpers::invoke(handler, handler.handler_); + ASIO_HANDLER_INVOCATION_END; + } + } + } + +private: + socket_ops::weak_cancel_token_type cancel_token_; + query_type query_; + io_service_impl& io_service_impl_; + Handler handler_; + asio::error_code ec_; + asio::detail::addrinfo_type* addrinfo_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_RESOLVE_OP_HPP diff --git a/asio-1.10.6/include/asio/detail/resolver_service.hpp b/asio-1.10.6/include/asio/detail/resolver_service.hpp new file mode 100644 index 0000000..7464428 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/resolver_service.hpp @@ -0,0 +1,124 @@ +// +// detail/resolver_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_RESOLVER_SERVICE_HPP +#define ASIO_DETAIL_RESOLVER_SERVICE_HPP + + +#include "asio/detail/config.hpp" + + +#include "asio/ip/basic_resolver_iterator.hpp" +#include "asio/ip/basic_resolver_query.hpp" +#include "asio/detail/addressof.hpp" +#include "asio/detail/resolve_endpoint_op.hpp" +#include "asio/detail/resolve_op.hpp" +#include "asio/detail/resolver_service_base.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename Protocol> +class resolver_service : public resolver_service_base +{ +public: + // The implementation type of the resolver. A cancellation token is used to + // indicate to the background thread that the operation has been cancelled. + typedef socket_ops::shared_cancel_token_type implementation_type; + + // The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + // The query type. + typedef asio::ip::basic_resolver_query<Protocol> query_type; + + // The iterator type. + typedef asio::ip::basic_resolver_iterator<Protocol> iterator_type; + + // Constructor. + resolver_service(asio::io_service& io_service) + : resolver_service_base(io_service) + { + } + + // Resolve a query to a list of entries. + iterator_type resolve(implementation_type&, const query_type& query, + asio::error_code& ec) + { + asio::detail::addrinfo_type* address_info = 0; + + socket_ops::getaddrinfo(query.host_name().c_str(), + query.service_name().c_str(), query.hints(), &address_info, ec); + auto_addrinfo auto_address_info(address_info); + + return ec ? iterator_type() : iterator_type::create( + address_info, query.host_name(), query.service_name()); + } + + // Asynchronously resolve a query to a list of entries. + template <typename Handler> + void async_resolve(implementation_type& impl, + const query_type& query, Handler& handler) + { + // Allocate and construct an operation to wrap the handler. + typedef resolve_op<Protocol, Handler> op; + typename op::ptr p = { asio::detail::addressof(handler), + asio_handler_alloc_helpers::allocate( + sizeof(op), handler), 0 }; + p.p = new (p.v) op(impl, query, io_service_impl_, handler); + + ASIO_HANDLER_CREATION((p.p, "resolver", &impl, "async_resolve")); + + start_resolve_op(p.p); + p.v = p.p = 0; + } + + // Resolve an endpoint to a list of entries. + iterator_type resolve(implementation_type&, + const endpoint_type& endpoint, asio::error_code& ec) + { + char host_name[NI_MAXHOST]; + char service_name[NI_MAXSERV]; + socket_ops::sync_getnameinfo(endpoint.data(), endpoint.size(), + host_name, NI_MAXHOST, service_name, NI_MAXSERV, + endpoint.protocol().type(), ec); + + return ec ? iterator_type() : iterator_type::create( + endpoint, host_name, service_name); + } + + // Asynchronously resolve an endpoint to a list of entries. + template <typename Handler> + void async_resolve(implementation_type& impl, + const endpoint_type& endpoint, Handler& handler) + { + // Allocate and construct an operation to wrap the handler. + typedef resolve_endpoint_op<Protocol, Handler> op; + typename op::ptr p = { asio::detail::addressof(handler), + asio_handler_alloc_helpers::allocate( + sizeof(op), handler), 0 }; + p.p = new (p.v) op(impl, endpoint, io_service_impl_, handler); + + ASIO_HANDLER_CREATION((p.p, "resolver", &impl, "async_resolve")); + + start_resolve_op(p.p); + p.v = p.p = 0; + } +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + + +#endif // ASIO_DETAIL_RESOLVER_SERVICE_HPP diff --git a/asio-1.10.6/include/asio/detail/resolver_service_base.hpp b/asio-1.10.6/include/asio/detail/resolver_service_base.hpp new file mode 100644 index 0000000..aac6860 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/resolver_service_base.hpp @@ -0,0 +1,122 @@ +// +// detail/resolver_service_base.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_RESOLVER_SERVICE_BASE_HPP +#define ASIO_DETAIL_RESOLVER_SERVICE_BASE_HPP + + +#include "asio/detail/config.hpp" +#include "asio/error.hpp" +#include "asio/io_service.hpp" +#include "asio/detail/mutex.hpp" +#include "asio/detail/noncopyable.hpp" +#include "asio/detail/operation.hpp" +#include "asio/detail/socket_ops.hpp" +#include "asio/detail/socket_types.hpp" +#include "asio/detail/scoped_ptr.hpp" +#include "asio/detail/thread.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class resolver_service_base +{ +public: + // The implementation type of the resolver. A cancellation token is used to + // indicate to the background thread that the operation has been cancelled. + typedef socket_ops::shared_cancel_token_type implementation_type; + + // Constructor. + ASIO_DECL resolver_service_base(asio::io_service& io_service); + + // Destructor. + ASIO_DECL ~resolver_service_base(); + + // Destroy all user-defined handler objects owned by the service. + ASIO_DECL void shutdown_service(); + + // Perform any fork-related housekeeping. + ASIO_DECL void fork_service( + asio::io_service::fork_event fork_ev); + + // Construct a new resolver implementation. + ASIO_DECL void construct(implementation_type& impl); + + // Destroy a resolver implementation. + ASIO_DECL void destroy(implementation_type&); + + // Cancel pending asynchronous operations. + ASIO_DECL void cancel(implementation_type& impl); + +protected: + // Helper function to start an asynchronous resolve operation. + ASIO_DECL void start_resolve_op(operation* op); + + // Helper class to perform exception-safe cleanup of addrinfo objects. + class auto_addrinfo + : private asio::detail::noncopyable + { + public: + explicit auto_addrinfo(asio::detail::addrinfo_type* ai) + : ai_(ai) + { + } + + ~auto_addrinfo() + { + if (ai_) + socket_ops::freeaddrinfo(ai_); + } + + operator asio::detail::addrinfo_type*() + { + return ai_; + } + + private: + asio::detail::addrinfo_type* ai_; + }; + + // Helper class to run the work io_service in a thread. + class work_io_service_runner; + + // Start the work thread if it's not already running. + ASIO_DECL void start_work_thread(); + + // The io_service implementation used to post completions. + io_service_impl& io_service_impl_; + +private: + // Mutex to protect access to internal data. + asio::detail::mutex mutex_; + + // Private io_service used for performing asynchronous host resolution. + asio::detail::scoped_ptr<asio::io_service> work_io_service_; + + // The work io_service implementation used to post completions. + io_service_impl& work_io_service_impl_; + + // Work for the private io_service to perform. + asio::detail::scoped_ptr<asio::io_service::work> work_; + + // Thread used for running the work io_service's run loop. + asio::detail::scoped_ptr<asio::detail::thread> work_thread_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +# include "asio/detail/impl/resolver_service_base.ipp" + +#endif // ASIO_DETAIL_RESOLVER_SERVICE_BASE_HPP diff --git a/asio-1.10.6/include/asio/detail/scoped_lock.hpp b/asio-1.10.6/include/asio/detail/scoped_lock.hpp new file mode 100644 index 0000000..f0ff643 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/scoped_lock.hpp @@ -0,0 +1,98 @@ +// +// detail/scoped_lock.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_SCOPED_LOCK_HPP +#define ASIO_DETAIL_SCOPED_LOCK_HPP + + +#include "asio/detail/noncopyable.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +// Helper class to lock and unlock a mutex automatically. +template <typename Mutex> +class scoped_lock + : private noncopyable +{ +public: + // Tag type used to distinguish constructors. + enum adopt_lock_t { adopt_lock }; + + // Constructor adopts a lock that is already held. + scoped_lock(Mutex& m, adopt_lock_t) + : mutex_(m), + locked_(true) + { + } + + // Constructor acquires the lock. + explicit scoped_lock(Mutex& m) + : mutex_(m) + { + mutex_.lock(); + locked_ = true; + } + + // Destructor releases the lock. + ~scoped_lock() + { + if (locked_) + mutex_.unlock(); + } + + // Explicitly acquire the lock. + void lock() + { + if (!locked_) + { + mutex_.lock(); + locked_ = true; + } + } + + // Explicitly release the lock. + void unlock() + { + if (locked_) + { + mutex_.unlock(); + locked_ = false; + } + } + + // Test whether the lock is held. + bool locked() const + { + return locked_; + } + + // Get the underlying mutex. + Mutex& mutex() + { + return mutex_; + } + +private: + // The underlying mutex. + Mutex& mutex_; + + // Whether the mutex is currently locked or unlocked. + bool locked_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_SCOPED_LOCK_HPP diff --git a/asio-1.10.6/include/asio/detail/scoped_ptr.hpp b/asio-1.10.6/include/asio/detail/scoped_ptr.hpp new file mode 100644 index 0000000..03c65c0 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/scoped_ptr.hpp @@ -0,0 +1,76 @@ +// +// detail/scoped_ptr.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_SCOPED_PTR_HPP +#define ASIO_DETAIL_SCOPED_PTR_HPP + + +#include "asio/detail/config.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename T> +class scoped_ptr +{ +public: + // Constructor. + explicit scoped_ptr(T* p = 0) + : p_(p) + { + } + + // Destructor. + ~scoped_ptr() + { + delete p_; + } + + // Access. + T* get() + { + return p_; + } + + // Access. + T* operator->() + { + return p_; + } + + // Dereference. + T& operator*() + { + return *p_; + } + + // Reset pointer. + void reset(T* p = 0) + { + delete p_; + p_ = p; + } + +private: + // Disallow copying and assignment. + scoped_ptr(const scoped_ptr&); + scoped_ptr& operator=(const scoped_ptr&); + + T* p_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_SCOPED_PTR_HPP diff --git a/asio-1.10.6/include/asio/detail/select_interrupter.hpp b/asio-1.10.6/include/asio/detail/select_interrupter.hpp new file mode 100644 index 0000000..9a8d639 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/select_interrupter.hpp @@ -0,0 +1,29 @@ +// +// detail/select_interrupter.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_SELECT_INTERRUPTER_HPP +#define ASIO_DETAIL_SELECT_INTERRUPTER_HPP + + +#include "asio/detail/config.hpp" + + +# include "asio/detail/pipe_select_interrupter.hpp" + +namespace asio { +namespace detail { + +typedef pipe_select_interrupter select_interrupter; + +} // namespace detail +} // namespace asio + + +#endif // ASIO_DETAIL_SELECT_INTERRUPTER_HPP diff --git a/asio-1.10.6/include/asio/detail/select_reactor.hpp b/asio-1.10.6/include/asio/detail/select_reactor.hpp new file mode 100644 index 0000000..e0f06db --- /dev/null +++ b/asio-1.10.6/include/asio/detail/select_reactor.hpp @@ -0,0 +1,188 @@ +// +// detail/select_reactor.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_SELECT_REACTOR_HPP +#define ASIO_DETAIL_SELECT_REACTOR_HPP + + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_IOCP) || (!defined(ASIO_HAS_DEV_POLL) && !defined(ASIO_HAS_EPOLL) && !defined(ASIO_HAS_KQUEUE) && !defined(ASIO_WINDOWS_RUNTIME)) + +#include <cstddef> +#include "asio/detail/fd_set_adapter.hpp" +#include "asio/detail/limits.hpp" +#include "asio/detail/mutex.hpp" +#include "asio/detail/op_queue.hpp" +#include "asio/detail/reactor_op.hpp" +#include "asio/detail/reactor_op_queue.hpp" +#include "asio/detail/select_interrupter.hpp" +#include "asio/detail/socket_types.hpp" +#include "asio/detail/timer_queue_base.hpp" +#include "asio/detail/timer_queue_set.hpp" +#include "asio/detail/wait_op.hpp" +#include "asio/io_service.hpp" + + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class select_reactor + : public asio::detail::service_base<select_reactor> +{ +public: + enum op_types { read_op = 0, write_op = 1, except_op = 2, + max_select_ops = 3, connect_op = 1, max_ops = 3 }; + + // Per-descriptor data. + struct per_descriptor_data + { + }; + + // Constructor. + ASIO_DECL select_reactor(asio::io_service& io_service); + + // Destructor. + ASIO_DECL ~select_reactor(); + + // Destroy all user-defined handler objects owned by the service. + ASIO_DECL void shutdown_service(); + + // Recreate internal descriptors following a fork. + ASIO_DECL void fork_service( + asio::io_service::fork_event fork_ev); + + // Initialise the task, but only if the reactor is not in its own thread. + ASIO_DECL void init_task(); + + // Register a socket with the reactor. Returns 0 on success, system error + // code on failure. + ASIO_DECL int register_descriptor(socket_type, per_descriptor_data&); + + // Register a descriptor with an associated single operation. Returns 0 on + // success, system error code on failure. + ASIO_DECL int register_internal_descriptor( + int op_type, socket_type descriptor, + per_descriptor_data& descriptor_data, reactor_op* op); + + // Post a reactor operation for immediate completion. + void post_immediate_completion(reactor_op* op, bool is_continuation) + { + io_service_.post_immediate_completion(op, is_continuation); + } + + // Start a new operation. The reactor operation will be performed when the + // given descriptor is flagged as ready, or an error has occurred. + ASIO_DECL void start_op(int op_type, socket_type descriptor, + per_descriptor_data&, reactor_op* op, bool is_continuation, bool); + + // Cancel all operations associated with the given descriptor. The + // handlers associated with the descriptor will be invoked with the + // operation_aborted error. + ASIO_DECL void cancel_ops(socket_type descriptor, per_descriptor_data&); + + // Cancel any operations that are running against the descriptor and remove + // its registration from the reactor. + ASIO_DECL void deregister_descriptor(socket_type descriptor, + per_descriptor_data&, bool closing); + + // Remote the descriptor's registration from the reactor. + ASIO_DECL void deregister_internal_descriptor( + socket_type descriptor, per_descriptor_data& descriptor_data); + + // Move descriptor registration from one descriptor_data object to another. + ASIO_DECL void move_descriptor(socket_type descriptor, + per_descriptor_data& target_descriptor_data, + per_descriptor_data& source_descriptor_data); + + // Add a new timer queue to the reactor. + template <typename Time_Traits> + void add_timer_queue(timer_queue<Time_Traits>& queue); + + // Remove a timer queue from the reactor. + template <typename Time_Traits> + void remove_timer_queue(timer_queue<Time_Traits>& queue); + + // Schedule a new operation in the given timer queue to expire at the + // specified absolute time. + template <typename Time_Traits> + void schedule_timer(timer_queue<Time_Traits>& queue, + const typename Time_Traits::time_type& time, + typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op); + + // Cancel the timer operations associated with the given token. Returns the + // number of operations that have been posted or dispatched. + template <typename Time_Traits> + std::size_t cancel_timer(timer_queue<Time_Traits>& queue, + typename timer_queue<Time_Traits>::per_timer_data& timer, + std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)()); + + // Run select once until interrupted or events are ready to be dispatched. + ASIO_DECL void run(bool block, op_queue<operation>& ops); + + // Interrupt the select loop. + ASIO_DECL void interrupt(); + +private: + + // Helper function to add a new timer queue. + ASIO_DECL void do_add_timer_queue(timer_queue_base& queue); + + // Helper function to remove a timer queue. + ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue); + + // Get the timeout value for the select call. + ASIO_DECL timeval* get_timeout(timeval& tv); + + // Cancel all operations associated with the given descriptor. This function + // does not acquire the select_reactor's mutex. + ASIO_DECL void cancel_ops_unlocked(socket_type descriptor, + const asio::error_code& ec); + + // The io_service implementation used to post completions. + io_service_impl& io_service_; + + // Mutex to protect access to internal data. + asio::detail::mutex mutex_; + + // The interrupter is used to break a blocking select call. + select_interrupter interrupter_; + + // The queues of read, write and except operations. + reactor_op_queue<socket_type> op_queue_[max_ops]; + + // The file descriptor sets to be passed to the select system call. + fd_set_adapter fd_sets_[max_select_ops]; + + // The timer queues. + timer_queue_set timer_queues_; + + + // Whether the service has been shut down. + bool shutdown_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#include "asio/detail/impl/select_reactor.hpp" +# include "asio/detail/impl/select_reactor.ipp" + +#endif // defined(ASIO_HAS_IOCP) + // || (!defined(ASIO_HAS_DEV_POLL) + // && !defined(ASIO_HAS_EPOLL) + // && !defined(ASIO_HAS_KQUEUE) + // && !defined(ASIO_WINDOWS_RUNTIME)) + +#endif // ASIO_DETAIL_SELECT_REACTOR_HPP diff --git a/asio-1.10.6/include/asio/detail/service_registry.hpp b/asio-1.10.6/include/asio/detail/service_registry.hpp new file mode 100644 index 0000000..b69eba2 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/service_registry.hpp @@ -0,0 +1,139 @@ +// +// detail/service_registry.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_SERVICE_REGISTRY_HPP +#define ASIO_DETAIL_SERVICE_REGISTRY_HPP + + +#include "asio/detail/config.hpp" +#include <typeinfo> +#include "asio/detail/mutex.hpp" +#include "asio/detail/noncopyable.hpp" +#include "asio/io_service.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename T> +class typeid_wrapper {}; + +class service_registry + : private noncopyable +{ +public: + // Constructor. Adds the initial service. + template <typename Service, typename Arg> + service_registry(asio::io_service& o, + Service* initial_service, Arg arg); + + // Destructor. + ASIO_DECL ~service_registry(); + + // Notify all services of a fork event. + ASIO_DECL void notify_fork(asio::io_service::fork_event fork_ev); + + // Get the first service object cast to the specified type. Called during + // io_service construction and so performs no locking or type checking. + template <typename Service> + Service& first_service(); + + // Get the service object corresponding to the specified service type. Will + // create a new service object automatically if no such object already + // exists. Ownership of the service object is not transferred to the caller. + template <typename Service> + Service& use_service(); + + // Add a service object. Throws on error, in which case ownership of the + // object is retained by the caller. + template <typename Service> + void add_service(Service* new_service); + + // Check whether a service object of the specified type already exists. + template <typename Service> + bool has_service() const; + +private: + // Initialise a service's key based on its id. + ASIO_DECL static void init_key( + asio::io_service::service::key& key, + const asio::io_service::id& id); + +#if !defined(ASIO_NO_TYPEID) + // Initialise a service's key based on its id. + template <typename Service> + static void init_key(asio::io_service::service::key& key, + const asio::detail::service_id<Service>& /*id*/); +#endif // !defined(ASIO_NO_TYPEID) + + // Check if a service matches the given id. + ASIO_DECL static bool keys_match( + const asio::io_service::service::key& key1, + const asio::io_service::service::key& key2); + + // The type of a factory function used for creating a service instance. + typedef asio::io_service::service* + (*factory_type)(asio::io_service&); + + // Factory function for creating a service instance. + template <typename Service> + static asio::io_service::service* create( + asio::io_service& owner); + + // Destroy a service instance. + ASIO_DECL static void destroy( + asio::io_service::service* service); + + // Helper class to manage service pointers. + struct auto_service_ptr; + friend struct auto_service_ptr; + struct auto_service_ptr + { + asio::io_service::service* ptr_; + ~auto_service_ptr() { destroy(ptr_); } + }; + + // Get the service object corresponding to the specified service key. Will + // create a new service object automatically if no such object already + // exists. Ownership of the service object is not transferred to the caller. + ASIO_DECL asio::io_service::service* do_use_service( + const asio::io_service::service::key& key, + factory_type factory); + + // Add a service object. Throws on error, in which case ownership of the + // object is retained by the caller. + ASIO_DECL void do_add_service( + const asio::io_service::service::key& key, + asio::io_service::service* new_service); + + // Check whether a service object with the specified key already exists. + ASIO_DECL bool do_has_service( + const asio::io_service::service::key& key) const; + + // Mutex to protect access to internal data. + mutable asio::detail::mutex mutex_; + + // The owner of this service registry and the services it contains. + asio::io_service& owner_; + + // The first service in the list of contained services. + asio::io_service::service* first_service_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#include "asio/detail/impl/service_registry.hpp" +# include "asio/detail/impl/service_registry.ipp" + +#endif // ASIO_DETAIL_SERVICE_REGISTRY_HPP diff --git a/asio-1.10.6/include/asio/detail/shared_ptr.hpp b/asio-1.10.6/include/asio/detail/shared_ptr.hpp new file mode 100644 index 0000000..f3fc3ab --- /dev/null +++ b/asio-1.10.6/include/asio/detail/shared_ptr.hpp @@ -0,0 +1,27 @@ +// +// detail/shared_ptr.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_SHARED_PTR_HPP +#define ASIO_DETAIL_SHARED_PTR_HPP + + +#include "asio/detail/config.hpp" + +# include <memory> + +namespace asio { +namespace detail { + +using std::shared_ptr; + +} // namespace detail +} // namespace asio + +#endif // ASIO_DETAIL_SHARED_PTR_HPP diff --git a/asio-1.10.6/include/asio/detail/signal_blocker.hpp b/asio-1.10.6/include/asio/detail/signal_blocker.hpp new file mode 100644 index 0000000..3e96c05 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/signal_blocker.hpp @@ -0,0 +1,33 @@ +// +// detail/signal_blocker.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_SIGNAL_BLOCKER_HPP +#define ASIO_DETAIL_SIGNAL_BLOCKER_HPP + + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_PTHREADS) +# include "asio/detail/posix_signal_blocker.hpp" +#else +# error Only Windows and POSIX are supported! +#endif + +namespace asio { +namespace detail { + +#if defined(ASIO_HAS_PTHREADS) +typedef posix_signal_blocker signal_blocker; +#endif + +} // namespace detail +} // namespace asio + +#endif // ASIO_DETAIL_SIGNAL_BLOCKER_HPP diff --git a/asio-1.10.6/include/asio/detail/socket_holder.hpp b/asio-1.10.6/include/asio/detail/socket_holder.hpp new file mode 100644 index 0000000..7bd3475 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/socket_holder.hpp @@ -0,0 +1,95 @@ +// +// detail/socket_holder.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_SOCKET_HOLDER_HPP +#define ASIO_DETAIL_SOCKET_HOLDER_HPP + + +#include "asio/detail/config.hpp" +#include "asio/detail/noncopyable.hpp" +#include "asio/detail/socket_ops.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +// Implement the resource acquisition is initialisation idiom for sockets. +class socket_holder + : private noncopyable +{ +public: + // Construct as an uninitialised socket. + socket_holder() + : socket_(invalid_socket) + { + } + + // Construct to take ownership of the specified socket. + explicit socket_holder(socket_type s) + : socket_(s) + { + } + + // Destructor. + ~socket_holder() + { + if (socket_ != invalid_socket) + { + asio::error_code ec; + socket_ops::state_type state = 0; + socket_ops::close(socket_, state, true, ec); + } + } + + // Get the underlying socket. + socket_type get() const + { + return socket_; + } + + // Reset to an uninitialised socket. + void reset() + { + if (socket_ != invalid_socket) + { + asio::error_code ec; + socket_ops::state_type state = 0; + socket_ops::close(socket_, state, true, ec); + socket_ = invalid_socket; + } + } + + // Reset to take ownership of the specified socket. + void reset(socket_type s) + { + reset(); + socket_ = s; + } + + // Release ownership of the socket. + socket_type release() + { + socket_type tmp = socket_; + socket_ = invalid_socket; + return tmp; + } + +private: + // The underlying socket. + socket_type socket_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_SOCKET_HOLDER_HPP diff --git a/asio-1.10.6/include/asio/detail/socket_ops.hpp b/asio-1.10.6/include/asio/detail/socket_ops.hpp new file mode 100644 index 0000000..e37a136 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/socket_ops.hpp @@ -0,0 +1,272 @@ +// +// detail/socket_ops.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_SOCKET_OPS_HPP +#define ASIO_DETAIL_SOCKET_OPS_HPP + + +#include "asio/detail/config.hpp" + +#include "asio/error_code.hpp" +#include "asio/detail/shared_ptr.hpp" +#include "asio/detail/socket_types.hpp" +#include "asio/detail/weak_ptr.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { +namespace socket_ops { + +// Socket state bits. +enum +{ + // The user wants a non-blocking socket. + user_set_non_blocking = 1, + + // The socket has been set non-blocking. + internal_non_blocking = 2, + + // Helper "state" used to determine whether the socket is non-blocking. + non_blocking = user_set_non_blocking | internal_non_blocking, + + // User wants connection_aborted errors, which are disabled by default. + enable_connection_aborted = 4, + + // The user set the linger option. Needs to be checked when closing. + user_set_linger = 8, + + // The socket is stream-oriented. + stream_oriented = 16, + + // The socket is datagram-oriented. + datagram_oriented = 32, + + // The socket may have been dup()-ed. + possible_dup = 64 +}; + +typedef unsigned char state_type; + +struct noop_deleter { void operator()(void*) {} }; +typedef shared_ptr<void> shared_cancel_token_type; +typedef weak_ptr<void> weak_cancel_token_type; + + +ASIO_DECL socket_type accept(socket_type s, socket_addr_type* addr, + std::size_t* addrlen, asio::error_code& ec); + +ASIO_DECL socket_type sync_accept(socket_type s, + state_type state, socket_addr_type* addr, + std::size_t* addrlen, asio::error_code& ec); + + +ASIO_DECL bool non_blocking_accept(socket_type s, + state_type state, socket_addr_type* addr, std::size_t* addrlen, + asio::error_code& ec, socket_type& new_socket); + + +ASIO_DECL int bind(socket_type s, const socket_addr_type* addr, + std::size_t addrlen, asio::error_code& ec); + +ASIO_DECL int close(socket_type s, state_type& state, + bool destruction, asio::error_code& ec); + +ASIO_DECL bool set_user_non_blocking(socket_type s, + state_type& state, bool value, asio::error_code& ec); + +ASIO_DECL bool set_internal_non_blocking(socket_type s, + state_type& state, bool value, asio::error_code& ec); + +ASIO_DECL int shutdown(socket_type s, + int what, asio::error_code& ec); + +ASIO_DECL int connect(socket_type s, const socket_addr_type* addr, + std::size_t addrlen, asio::error_code& ec); + +ASIO_DECL void sync_connect(socket_type s, const socket_addr_type* addr, + std::size_t addrlen, asio::error_code& ec); + + +ASIO_DECL bool non_blocking_connect(socket_type s, + asio::error_code& ec); + +ASIO_DECL int socketpair(int af, int type, int protocol, + socket_type sv[2], asio::error_code& ec); + +ASIO_DECL bool sockatmark(socket_type s, asio::error_code& ec); + +ASIO_DECL size_t available(socket_type s, asio::error_code& ec); + +ASIO_DECL int listen(socket_type s, + int backlog, asio::error_code& ec); + +typedef iovec buf; + +ASIO_DECL void init_buf(buf& b, void* data, size_t size); + +ASIO_DECL void init_buf(buf& b, const void* data, size_t size); + +ASIO_DECL signed_size_type recv(socket_type s, buf* bufs, + size_t count, int flags, asio::error_code& ec); + +ASIO_DECL size_t sync_recv(socket_type s, state_type state, buf* bufs, + size_t count, int flags, bool all_empty, asio::error_code& ec); + + +ASIO_DECL bool non_blocking_recv(socket_type s, + buf* bufs, size_t count, int flags, bool is_stream, + asio::error_code& ec, size_t& bytes_transferred); + + +ASIO_DECL signed_size_type recvfrom(socket_type s, buf* bufs, + size_t count, int flags, socket_addr_type* addr, + std::size_t* addrlen, asio::error_code& ec); + +ASIO_DECL size_t sync_recvfrom(socket_type s, state_type state, + buf* bufs, size_t count, int flags, socket_addr_type* addr, + std::size_t* addrlen, asio::error_code& ec); + + +ASIO_DECL bool non_blocking_recvfrom(socket_type s, + buf* bufs, size_t count, int flags, + socket_addr_type* addr, std::size_t* addrlen, + asio::error_code& ec, size_t& bytes_transferred); + + +ASIO_DECL signed_size_type recvmsg(socket_type s, buf* bufs, + size_t count, int in_flags, int& out_flags, + asio::error_code& ec); + +ASIO_DECL size_t sync_recvmsg(socket_type s, state_type state, + buf* bufs, size_t count, int in_flags, int& out_flags, + asio::error_code& ec); + + +ASIO_DECL bool non_blocking_recvmsg(socket_type s, + buf* bufs, size_t count, int in_flags, int& out_flags, + asio::error_code& ec, size_t& bytes_transferred); + + +ASIO_DECL signed_size_type send(socket_type s, const buf* bufs, + size_t count, int flags, asio::error_code& ec); + +ASIO_DECL size_t sync_send(socket_type s, state_type state, + const buf* bufs, size_t count, int flags, + bool all_empty, asio::error_code& ec); + + +ASIO_DECL bool non_blocking_send(socket_type s, + const buf* bufs, size_t count, int flags, + asio::error_code& ec, size_t& bytes_transferred); + + +ASIO_DECL signed_size_type sendto(socket_type s, const buf* bufs, + size_t count, int flags, const socket_addr_type* addr, + std::size_t addrlen, asio::error_code& ec); + +ASIO_DECL size_t sync_sendto(socket_type s, state_type state, + const buf* bufs, size_t count, int flags, const socket_addr_type* addr, + std::size_t addrlen, asio::error_code& ec); + + +ASIO_DECL bool non_blocking_sendto(socket_type s, + const buf* bufs, size_t count, int flags, + const socket_addr_type* addr, std::size_t addrlen, + asio::error_code& ec, size_t& bytes_transferred); + + +ASIO_DECL socket_type socket(int af, int type, int protocol, + asio::error_code& ec); + +ASIO_DECL int setsockopt(socket_type s, state_type& state, + int level, int optname, const void* optval, + std::size_t optlen, asio::error_code& ec); + +ASIO_DECL int getsockopt(socket_type s, state_type state, + int level, int optname, void* optval, + size_t* optlen, asio::error_code& ec); + +ASIO_DECL int getpeername(socket_type s, socket_addr_type* addr, + std::size_t* addrlen, bool cached, asio::error_code& ec); + +ASIO_DECL int getsockname(socket_type s, socket_addr_type* addr, + std::size_t* addrlen, asio::error_code& ec); + +ASIO_DECL int ioctl(socket_type s, state_type& state, + int cmd, ioctl_arg_type* arg, asio::error_code& ec); + +ASIO_DECL int select(int nfds, fd_set* readfds, fd_set* writefds, + fd_set* exceptfds, timeval* timeout, asio::error_code& ec); + +ASIO_DECL int poll_read(socket_type s, + state_type state, asio::error_code& ec); + +ASIO_DECL int poll_write(socket_type s, + state_type state, asio::error_code& ec); + +ASIO_DECL int poll_connect(socket_type s, asio::error_code& ec); + + +ASIO_DECL const char* inet_ntop(int af, const void* src, char* dest, + size_t length, unsigned long scope_id, asio::error_code& ec); + +ASIO_DECL int inet_pton(int af, const char* src, void* dest, + unsigned long* scope_id, asio::error_code& ec); + +ASIO_DECL int gethostname(char* name, + int namelen, asio::error_code& ec); + + +ASIO_DECL asio::error_code getaddrinfo(const char* host, + const char* service, const addrinfo_type& hints, + addrinfo_type** result, asio::error_code& ec); + +ASIO_DECL asio::error_code background_getaddrinfo( + const weak_cancel_token_type& cancel_token, const char* host, + const char* service, const addrinfo_type& hints, + addrinfo_type** result, asio::error_code& ec); + +ASIO_DECL void freeaddrinfo(addrinfo_type* ai); + +ASIO_DECL asio::error_code getnameinfo( + const socket_addr_type* addr, std::size_t addrlen, + char* host, std::size_t hostlen, char* serv, + std::size_t servlen, int flags, asio::error_code& ec); + +ASIO_DECL asio::error_code sync_getnameinfo( + const socket_addr_type* addr, std::size_t addrlen, + char* host, std::size_t hostlen, char* serv, + std::size_t servlen, int sock_type, asio::error_code& ec); + +ASIO_DECL asio::error_code background_getnameinfo( + const weak_cancel_token_type& cancel_token, + const socket_addr_type* addr, std::size_t addrlen, + char* host, std::size_t hostlen, char* serv, + std::size_t servlen, int sock_type, asio::error_code& ec); + + +ASIO_DECL u_long_type network_to_host_long(u_long_type value); + +ASIO_DECL u_long_type host_to_network_long(u_long_type value); + +ASIO_DECL u_short_type network_to_host_short(u_short_type value); + +ASIO_DECL u_short_type host_to_network_short(u_short_type value); + +} // namespace socket_ops +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +# include "asio/detail/impl/socket_ops.ipp" + +#endif // ASIO_DETAIL_SOCKET_OPS_HPP diff --git a/asio-1.10.6/include/asio/detail/socket_option.hpp b/asio-1.10.6/include/asio/detail/socket_option.hpp new file mode 100644 index 0000000..ae1efeb --- /dev/null +++ b/asio-1.10.6/include/asio/detail/socket_option.hpp @@ -0,0 +1,309 @@ +// +// detail/socket_option.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_SOCKET_OPTION_HPP +#define ASIO_DETAIL_SOCKET_OPTION_HPP + + +#include "asio/detail/config.hpp" +#include <cstddef> +#include <stdexcept> +#include "asio/detail/socket_types.hpp" +#include "asio/detail/throw_exception.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { +namespace socket_option { + +// Helper template for implementing boolean-based options. +template <int Level, int Name> +class boolean +{ +public: + // Default constructor. + boolean() + : value_(0) + { + } + + // Construct with a specific option value. + explicit boolean(bool v) + : value_(v ? 1 : 0) + { + } + + // Set the current value of the boolean. + boolean& operator=(bool v) + { + value_ = v ? 1 : 0; + return *this; + } + + // Get the current value of the boolean. + bool value() const + { + return !!value_; + } + + // Convert to bool. + operator bool() const + { + return !!value_; + } + + // Test for false. + bool operator!() const + { + return !value_; + } + + // Get the level of the socket option. + template <typename Protocol> + int level(const Protocol&) const + { + return Level; + } + + // Get the name of the socket option. + template <typename Protocol> + int name(const Protocol&) const + { + return Name; + } + + // Get the address of the boolean data. + template <typename Protocol> + int* data(const Protocol&) + { + return &value_; + } + + // Get the address of the boolean data. + template <typename Protocol> + const int* data(const Protocol&) const + { + return &value_; + } + + // Get the size of the boolean data. + template <typename Protocol> + std::size_t size(const Protocol&) const + { + return sizeof(value_); + } + + // Set the size of the boolean data. + template <typename Protocol> + void resize(const Protocol&, std::size_t s) + { + // On some platforms (e.g. Windows Vista), the getsockopt function will + // return the size of a boolean socket option as one byte, even though a + // four byte integer was passed in. + switch (s) + { + case sizeof(char): + value_ = *reinterpret_cast<char*>(&value_) ? 1 : 0; + break; + case sizeof(value_): + break; + default: + { + std::length_error ex("boolean socket option resize"); + asio::detail::throw_exception(ex); + } + } + } + +private: + int value_; +}; + +// Helper template for implementing integer options. +template <int Level, int Name> +class integer +{ +public: + // Default constructor. + integer() + : value_(0) + { + } + + // Construct with a specific option value. + explicit integer(int v) + : value_(v) + { + } + + // Set the value of the int option. + integer& operator=(int v) + { + value_ = v; + return *this; + } + + // Get the current value of the int option. + int value() const + { + return value_; + } + + // Get the level of the socket option. + template <typename Protocol> + int level(const Protocol&) const + { + return Level; + } + + // Get the name of the socket option. + template <typename Protocol> + int name(const Protocol&) const + { + return Name; + } + + // Get the address of the int data. + template <typename Protocol> + int* data(const Protocol&) + { + return &value_; + } + + // Get the address of the int data. + template <typename Protocol> + const int* data(const Protocol&) const + { + return &value_; + } + + // Get the size of the int data. + template <typename Protocol> + std::size_t size(const Protocol&) const + { + return sizeof(value_); + } + + // Set the size of the int data. + template <typename Protocol> + void resize(const Protocol&, std::size_t s) + { + if (s != sizeof(value_)) + { + std::length_error ex("integer socket option resize"); + asio::detail::throw_exception(ex); + } + } + +private: + int value_; +}; + +// Helper template for implementing linger options. +template <int Level, int Name> +class linger +{ +public: + // Default constructor. + linger() + { + value_.l_onoff = 0; + value_.l_linger = 0; + } + + // Construct with specific option values. + linger(bool e, int t) + { + enabled(e); + timeout ASIO_PREVENT_MACRO_SUBSTITUTION(t); + } + + // Set the value for whether linger is enabled. + void enabled(bool value) + { + value_.l_onoff = value ? 1 : 0; + } + + // Get the value for whether linger is enabled. + bool enabled() const + { + return value_.l_onoff != 0; + } + + // Set the value for the linger timeout. + void timeout ASIO_PREVENT_MACRO_SUBSTITUTION(int value) + { + value_.l_linger = value; + } + + // Get the value for the linger timeout. + int timeout ASIO_PREVENT_MACRO_SUBSTITUTION() const + { + return static_cast<int>(value_.l_linger); + } + + // Get the level of the socket option. + template <typename Protocol> + int level(const Protocol&) const + { + return Level; + } + + // Get the name of the socket option. + template <typename Protocol> + int name(const Protocol&) const + { + return Name; + } + + // Get the address of the linger data. + template <typename Protocol> + detail::linger_type* data(const Protocol&) + { + return &value_; + } + + // Get the address of the linger data. + template <typename Protocol> + const detail::linger_type* data(const Protocol&) const + { + return &value_; + } + + // Get the size of the linger data. + template <typename Protocol> + std::size_t size(const Protocol&) const + { + return sizeof(value_); + } + + // Set the size of the int data. + template <typename Protocol> + void resize(const Protocol&, std::size_t s) + { + if (s != sizeof(value_)) + { + std::length_error ex("linger socket option resize"); + asio::detail::throw_exception(ex); + } + } + +private: + detail::linger_type value_; +}; + +} // namespace socket_option +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_SOCKET_OPTION_HPP diff --git a/asio-1.10.6/include/asio/detail/socket_types.hpp b/asio-1.10.6/include/asio/detail/socket_types.hpp new file mode 100644 index 0000000..379f035 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/socket_types.hpp @@ -0,0 +1,173 @@ +// +// detail/socket_types.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_SOCKET_TYPES_HPP +#define ASIO_DETAIL_SOCKET_TYPES_HPP + + +#include "asio/detail/config.hpp" + +# include <sys/ioctl.h> +# include <sys/poll.h> +# include <sys/types.h> +# include <sys/stat.h> +# include <fcntl.h> +# if defined(__hpux) +# include <sys/time.h> +# endif +# if !defined(__hpux) || defined(__SELECT) +# include <sys/select.h> +# endif +# include <sys/socket.h> +# include <sys/uio.h> +# include <sys/un.h> +# include <netinet/in.h> +# include <netinet/tcp.h> +# include <arpa/inet.h> +# include <netdb.h> +# include <net/if.h> +# include <limits.h> +# if defined(__sun) +# include <sys/filio.h> +# include <sys/sockio.h> +# endif + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +typedef int socket_type; +const int invalid_socket = -1; +const int socket_error_retval = -1; +const int max_addr_v4_str_len = INET_ADDRSTRLEN; +#if defined(INET6_ADDRSTRLEN) +const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE; +#else // defined(INET6_ADDRSTRLEN) +const int max_addr_v6_str_len = 256; +#endif // defined(INET6_ADDRSTRLEN) +typedef sockaddr socket_addr_type; +typedef in_addr in4_addr_type; +# if defined(__hpux) +// HP-UX doesn't provide ip_mreq when _XOPEN_SOURCE_EXTENDED is defined. +struct in4_mreq_type +{ + struct in_addr imr_multiaddr; + struct in_addr imr_interface; +}; +# else +typedef ip_mreq in4_mreq_type; +# endif +typedef sockaddr_in sockaddr_in4_type; +typedef in6_addr in6_addr_type; +typedef ipv6_mreq in6_mreq_type; +typedef sockaddr_in6 sockaddr_in6_type; +typedef sockaddr_storage sockaddr_storage_type; +typedef sockaddr_un sockaddr_un_type; +typedef addrinfo addrinfo_type; +typedef ::linger linger_type; +typedef int ioctl_arg_type; +typedef uint32_t u_long_type; +typedef uint16_t u_short_type; +#if defined(ASIO_HAS_SSIZE_T) +typedef ssize_t signed_size_type; +#else // defined(ASIO_HAS_SSIZE_T) +typedef int signed_size_type; +#endif // defined(ASIO_HAS_SSIZE_T) +# define ASIO_OS_DEF(c) ASIO_OS_DEF_##c +# define ASIO_OS_DEF_AF_UNSPEC AF_UNSPEC +# define ASIO_OS_DEF_AF_INET AF_INET +# define ASIO_OS_DEF_AF_INET6 AF_INET6 +# define ASIO_OS_DEF_SOCK_STREAM SOCK_STREAM +# define ASIO_OS_DEF_SOCK_DGRAM SOCK_DGRAM +# define ASIO_OS_DEF_SOCK_RAW SOCK_RAW +# define ASIO_OS_DEF_SOCK_SEQPACKET SOCK_SEQPACKET +# define ASIO_OS_DEF_IPPROTO_IP IPPROTO_IP +# define ASIO_OS_DEF_IPPROTO_IPV6 IPPROTO_IPV6 +# define ASIO_OS_DEF_IPPROTO_TCP IPPROTO_TCP +# define ASIO_OS_DEF_IPPROTO_UDP IPPROTO_UDP +# define ASIO_OS_DEF_IPPROTO_ICMP IPPROTO_ICMP +# define ASIO_OS_DEF_IPPROTO_ICMPV6 IPPROTO_ICMPV6 +# define ASIO_OS_DEF_FIONBIO FIONBIO +# define ASIO_OS_DEF_FIONREAD FIONREAD +# define ASIO_OS_DEF_INADDR_ANY INADDR_ANY +# define ASIO_OS_DEF_MSG_OOB MSG_OOB +# define ASIO_OS_DEF_MSG_PEEK MSG_PEEK +# define ASIO_OS_DEF_MSG_DONTROUTE MSG_DONTROUTE +# define ASIO_OS_DEF_MSG_EOR MSG_EOR +# define ASIO_OS_DEF_SHUT_RD SHUT_RD +# define ASIO_OS_DEF_SHUT_WR SHUT_WR +# define ASIO_OS_DEF_SHUT_RDWR SHUT_RDWR +# define ASIO_OS_DEF_SOMAXCONN SOMAXCONN +# define ASIO_OS_DEF_SOL_SOCKET SOL_SOCKET +# define ASIO_OS_DEF_SO_BROADCAST SO_BROADCAST +# define ASIO_OS_DEF_SO_DEBUG SO_DEBUG +# define ASIO_OS_DEF_SO_DONTROUTE SO_DONTROUTE +# define ASIO_OS_DEF_SO_KEEPALIVE SO_KEEPALIVE +# define ASIO_OS_DEF_SO_LINGER SO_LINGER +# define ASIO_OS_DEF_SO_SNDBUF SO_SNDBUF +# define ASIO_OS_DEF_SO_RCVBUF SO_RCVBUF +# define ASIO_OS_DEF_SO_SNDLOWAT SO_SNDLOWAT +# define ASIO_OS_DEF_SO_RCVLOWAT SO_RCVLOWAT +# define ASIO_OS_DEF_SO_REUSEADDR SO_REUSEADDR +# define ASIO_OS_DEF_TCP_NODELAY TCP_NODELAY +# define ASIO_OS_DEF_IP_MULTICAST_IF IP_MULTICAST_IF +# define ASIO_OS_DEF_IP_MULTICAST_TTL IP_MULTICAST_TTL +# define ASIO_OS_DEF_IP_MULTICAST_LOOP IP_MULTICAST_LOOP +# define ASIO_OS_DEF_IP_ADD_MEMBERSHIP IP_ADD_MEMBERSHIP +# define ASIO_OS_DEF_IP_DROP_MEMBERSHIP IP_DROP_MEMBERSHIP +# define ASIO_OS_DEF_IP_TTL IP_TTL +# define ASIO_OS_DEF_IPV6_UNICAST_HOPS IPV6_UNICAST_HOPS +# define ASIO_OS_DEF_IPV6_MULTICAST_IF IPV6_MULTICAST_IF +# define ASIO_OS_DEF_IPV6_MULTICAST_HOPS IPV6_MULTICAST_HOPS +# define ASIO_OS_DEF_IPV6_MULTICAST_LOOP IPV6_MULTICAST_LOOP +# define ASIO_OS_DEF_IPV6_JOIN_GROUP IPV6_JOIN_GROUP +# define ASIO_OS_DEF_IPV6_LEAVE_GROUP IPV6_LEAVE_GROUP +# define ASIO_OS_DEF_AI_CANONNAME AI_CANONNAME +# define ASIO_OS_DEF_AI_PASSIVE AI_PASSIVE +# define ASIO_OS_DEF_AI_NUMERICHOST AI_NUMERICHOST +# if defined(AI_NUMERICSERV) +# define ASIO_OS_DEF_AI_NUMERICSERV AI_NUMERICSERV +# else +# define ASIO_OS_DEF_AI_NUMERICSERV 0 +# endif +// Note: QNX Neutrino 6.3 defines AI_V4MAPPED, AI_ALL and AI_ADDRCONFIG but +// does not implement them. Therefore they are specifically excluded here. +# if defined(AI_V4MAPPED) && !defined(__QNXNTO__) +# define ASIO_OS_DEF_AI_V4MAPPED AI_V4MAPPED +# else +# define ASIO_OS_DEF_AI_V4MAPPED 0 +# endif +# if defined(AI_ALL) && !defined(__QNXNTO__) +# define ASIO_OS_DEF_AI_ALL AI_ALL +# else +# define ASIO_OS_DEF_AI_ALL 0 +# endif +# if defined(AI_ADDRCONFIG) && !defined(__QNXNTO__) +# define ASIO_OS_DEF_AI_ADDRCONFIG AI_ADDRCONFIG +# else +# define ASIO_OS_DEF_AI_ADDRCONFIG 0 +# endif +# if defined(IOV_MAX) +const int max_iov_len = IOV_MAX; +# else +// POSIX platforms are not required to define IOV_MAX. +const int max_iov_len = 16; +# endif +const int custom_socket_option_level = 0xA5100000; +const int enable_connection_aborted_option = 1; +const int always_fail_option = 2; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_SOCKET_TYPES_HPP diff --git a/asio-1.10.6/include/asio/detail/task_io_service.hpp b/asio-1.10.6/include/asio/detail/task_io_service.hpp new file mode 100644 index 0000000..ea05242 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/task_io_service.hpp @@ -0,0 +1,194 @@ +// +// detail/task_io_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_TASK_IO_SERVICE_HPP +#define ASIO_DETAIL_TASK_IO_SERVICE_HPP + + +#include "asio/detail/config.hpp" + + +#include "asio/error_code.hpp" +#include "asio/io_service.hpp" +#include "asio/detail/atomic_count.hpp" +#include "asio/detail/call_stack.hpp" +#include "asio/detail/event.hpp" +#include "asio/detail/mutex.hpp" +#include "asio/detail/op_queue.hpp" +#include "asio/detail/reactor_fwd.hpp" +#include "asio/detail/task_io_service_operation.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +struct task_io_service_thread_info; + +class task_io_service + : public asio::detail::service_base<task_io_service> +{ +public: + typedef task_io_service_operation operation; + + // Constructor. Specifies the number of concurrent threads that are likely to + // run the io_service. If set to 1 certain optimisation are performed. + ASIO_DECL task_io_service(asio::io_service& io_service, + std::size_t concurrency_hint = 0); + + // Destroy all user-defined handler objects owned by the service. + ASIO_DECL void shutdown_service(); + + // Initialise the task, if required. + ASIO_DECL void init_task(); + + // Run the event loop until interrupted or no more work. + ASIO_DECL std::size_t run(asio::error_code& ec); + + // Run until interrupted or one operation is performed. + ASIO_DECL std::size_t run_one(asio::error_code& ec); + + // Poll for operations without blocking. + ASIO_DECL std::size_t poll(asio::error_code& ec); + + // Poll for one operation without blocking. + ASIO_DECL std::size_t poll_one(asio::error_code& ec); + + // Interrupt the event processing loop. + ASIO_DECL void stop(); + + // Determine whether the io_service is stopped. + ASIO_DECL bool stopped() const; + + // Reset in preparation for a subsequent run invocation. + ASIO_DECL void reset(); + + // Notify that some work has started. + void work_started() + { + ++outstanding_work_; + } + + // Notify that some work has finished. + void work_finished() + { + if (--outstanding_work_ == 0) + stop(); + } + + // Return whether a handler can be dispatched immediately. + bool can_dispatch() + { + return thread_call_stack::contains(this) != 0; + } + + // Request invocation of the given handler. + template <typename Handler> + void dispatch(Handler& handler); + + // Request invocation of the given handler and return immediately. + template <typename Handler> + void post(Handler& handler); + + // Request invocation of the given operation and return immediately. Assumes + // that work_started() has not yet been called for the operation. + ASIO_DECL void post_immediate_completion( + operation* op, bool is_continuation); + + // Request invocation of the given operation and return immediately. Assumes + // that work_started() was previously called for the operation. + ASIO_DECL void post_deferred_completion(operation* op); + + // Request invocation of the given operations and return immediately. Assumes + // that work_started() was previously called for each operation. + ASIO_DECL void post_deferred_completions(op_queue<operation>& ops); + + // Process unfinished operations as part of a shutdown_service operation. + // Assumes that work_started() was previously called for the operations. + ASIO_DECL void abandon_operations(op_queue<operation>& ops); + +private: + // Structure containing thread-specific data. + typedef task_io_service_thread_info thread_info; + + // Enqueue the given operation following a failed attempt to dispatch the + // operation for immediate invocation. + ASIO_DECL void do_dispatch(operation* op); + + // Run at most one operation. May block. + ASIO_DECL std::size_t do_run_one(mutex::scoped_lock& lock, + thread_info& this_thread, const asio::error_code& ec); + + // Poll for at most one operation. + ASIO_DECL std::size_t do_poll_one(mutex::scoped_lock& lock, + thread_info& this_thread, const asio::error_code& ec); + + // Stop the task and all idle threads. + ASIO_DECL void stop_all_threads(mutex::scoped_lock& lock); + + // Wake a single idle thread, or the task, and always unlock the mutex. + ASIO_DECL void wake_one_thread_and_unlock( + mutex::scoped_lock& lock); + + // Helper class to perform task-related operations on block exit. + struct task_cleanup; + friend struct task_cleanup; + + // Helper class to call work-related operations on block exit. + struct work_cleanup; + friend struct work_cleanup; + + // Whether to optimise for single-threaded use cases. + const bool one_thread_; + + // Mutex to protect access to internal data. + mutable mutex mutex_; + + // Event to wake up blocked threads. + event wakeup_event_; + + // The task to be run by this service. + reactor* task_; + + // Operation object to represent the position of the task in the queue. + struct task_operation : operation + { + task_operation() : operation(0) {} + } task_operation_; + + // Whether the task has been interrupted. + bool task_interrupted_; + + // The count of unfinished work. + atomic_count outstanding_work_; + + // The queue of handlers that are ready to be delivered. + op_queue<operation> op_queue_; + + // Flag to indicate that the dispatcher has been stopped. + bool stopped_; + + // Flag to indicate that the dispatcher has been shut down. + bool shutdown_; + + // Per-thread call stack to track the state of each thread in the io_service. + typedef call_stack<task_io_service, thread_info> thread_call_stack; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#include "asio/detail/impl/task_io_service.hpp" +# include "asio/detail/impl/task_io_service.ipp" + + +#endif // ASIO_DETAIL_TASK_IO_SERVICE_HPP diff --git a/asio-1.10.6/include/asio/detail/task_io_service_operation.hpp b/asio-1.10.6/include/asio/detail/task_io_service_operation.hpp new file mode 100644 index 0000000..0885ef0 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/task_io_service_operation.hpp @@ -0,0 +1,73 @@ +// +// detail/task_io_service_operation.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_TASK_IO_SERVICE_OPERATION_HPP +#define ASIO_DETAIL_TASK_IO_SERVICE_OPERATION_HPP + + +#include "asio/error_code.hpp" +#include "asio/detail/handler_tracking.hpp" +#include "asio/detail/op_queue.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class task_io_service; + +// Base class for all operations. A function pointer is used instead of virtual +// functions to avoid the associated overhead. +class task_io_service_operation ASIO_INHERIT_TRACKED_HANDLER +{ +public: + void complete(task_io_service& owner, + const asio::error_code& ec, std::size_t bytes_transferred) + { + func_(&owner, this, ec, bytes_transferred); + } + + void destroy() + { + func_(0, this, asio::error_code(), 0); + } + +protected: + typedef void (*func_type)(task_io_service*, + task_io_service_operation*, + const asio::error_code&, std::size_t); + + task_io_service_operation(func_type func) + : next_(0), + func_(func), + task_result_(0) + { + } + + // Prevents deletion through this type. + ~task_io_service_operation() + { + } + +private: + friend class op_queue_access; + task_io_service_operation* next_; + func_type func_; +protected: + friend class task_io_service; + unsigned int task_result_; // Passed into bytes transferred. +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_TASK_IO_SERVICE_OPERATION_HPP diff --git a/asio-1.10.6/include/asio/detail/task_io_service_thread_info.hpp b/asio-1.10.6/include/asio/detail/task_io_service_thread_info.hpp new file mode 100644 index 0000000..7b892e8 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/task_io_service_thread_info.hpp @@ -0,0 +1,37 @@ +// +// detail/task_io_service_thread_info.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_TASK_IO_SERVICE_THREAD_INFO_HPP +#define ASIO_DETAIL_TASK_IO_SERVICE_THREAD_INFO_HPP + + +#include "asio/detail/op_queue.hpp" +#include "asio/detail/thread_info_base.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class task_io_service; +class task_io_service_operation; + +struct task_io_service_thread_info : public thread_info_base +{ + op_queue<task_io_service_operation> private_op_queue; + long private_outstanding_work; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_TASK_IO_SERVICE_THREAD_INFO_HPP diff --git a/asio-1.10.6/include/asio/detail/thread.hpp b/asio-1.10.6/include/asio/detail/thread.hpp new file mode 100644 index 0000000..1bbed33 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/thread.hpp @@ -0,0 +1,35 @@ +// +// detail/thread.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_THREAD_HPP +#define ASIO_DETAIL_THREAD_HPP + + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_PTHREADS) +# include "asio/detail/posix_thread.hpp" +#else +# include "asio/detail/std_thread.hpp" +#endif + +namespace asio { +namespace detail { + +#if defined(ASIO_HAS_PTHREADS) +typedef posix_thread thread; +#else +typedef std_thread thread; +#endif + +} // namespace detail +} // namespace asio + +#endif // ASIO_DETAIL_THREAD_HPP diff --git a/asio-1.10.6/include/asio/detail/thread_info_base.hpp b/asio-1.10.6/include/asio/detail/thread_info_base.hpp new file mode 100644 index 0000000..5cfdbef --- /dev/null +++ b/asio-1.10.6/include/asio/detail/thread_info_base.hpp @@ -0,0 +1,88 @@ +// +// detail/thread_info_base.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_THREAD_INFO_BASE_HPP +#define ASIO_DETAIL_THREAD_INFO_BASE_HPP + + +#include <climits> +#include <cstddef> +#include "asio/detail/noncopyable.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class thread_info_base + : private noncopyable +{ +public: + thread_info_base() + : reusable_memory_(0) + { + } + + ~thread_info_base() + { + if (reusable_memory_) + ::operator delete(reusable_memory_); + } + + static void* allocate(thread_info_base* this_thread, std::size_t size) + { + if (this_thread && this_thread->reusable_memory_) + { + void* const pointer = this_thread->reusable_memory_; + this_thread->reusable_memory_ = 0; + + unsigned char* const mem = static_cast<unsigned char*>(pointer); + if (static_cast<std::size_t>(mem[0]) >= size) + { + mem[size] = mem[0]; + return pointer; + } + + ::operator delete(pointer); + } + + void* const pointer = ::operator new(size + 1); + unsigned char* const mem = static_cast<unsigned char*>(pointer); + mem[size] = (size <= UCHAR_MAX) ? static_cast<unsigned char>(size) : 0; + return pointer; + } + + static void deallocate(thread_info_base* this_thread, + void* pointer, std::size_t size) + { + if (size <= UCHAR_MAX) + { + if (this_thread && this_thread->reusable_memory_ == 0) + { + unsigned char* const mem = static_cast<unsigned char*>(pointer); + mem[0] = mem[size]; + this_thread->reusable_memory_ = pointer; + return; + } + } + + ::operator delete(pointer); + } + +private: + void* reusable_memory_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_THREAD_INFO_BASE_HPP diff --git a/asio-1.10.6/include/asio/detail/throw_error.hpp b/asio-1.10.6/include/asio/detail/throw_error.hpp new file mode 100644 index 0000000..2718080 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/throw_error.hpp @@ -0,0 +1,48 @@ +// +// detail/throw_error.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_THROW_ERROR_HPP +#define ASIO_DETAIL_THROW_ERROR_HPP + + +#include "asio/detail/config.hpp" +#include "asio/error_code.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +ASIO_DECL void do_throw_error(const asio::error_code& err); + +ASIO_DECL void do_throw_error(const asio::error_code& err, + const char* location); + +inline void throw_error(const asio::error_code& err) +{ + if (err) + do_throw_error(err); +} + +inline void throw_error(const asio::error_code& err, + const char* location) +{ + if (err) + do_throw_error(err, location); +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +# include "asio/detail/impl/throw_error.ipp" + +#endif // ASIO_DETAIL_THROW_ERROR_HPP diff --git a/asio-1.10.6/include/asio/detail/throw_exception.hpp b/asio-1.10.6/include/asio/detail/throw_exception.hpp new file mode 100644 index 0000000..8a98a54 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/throw_exception.hpp @@ -0,0 +1,41 @@ +// +// detail/throw_exception.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_THROW_EXCEPTION_HPP +#define ASIO_DETAIL_THROW_EXCEPTION_HPP + + +#include "asio/detail/config.hpp" + + +namespace asio { +namespace detail { + + +// Declare the throw_exception function for all targets. +template <typename Exception> +void throw_exception(const Exception& e); + +// Only define the throw_exception function when exceptions are enabled. +// Otherwise, it is up to the application to provide a definition of this +// function. +# if !defined(ASIO_NO_EXCEPTIONS) +template <typename Exception> +void throw_exception(const Exception& e) +{ + throw e; +} +# endif // !defined(ASIO_NO_EXCEPTIONS) + + +} // namespace detail +} // namespace asio + +#endif // ASIO_DETAIL_THROW_EXCEPTION_HPP diff --git a/asio-1.10.6/include/asio/detail/timer_queue_base.hpp b/asio-1.10.6/include/asio/detail/timer_queue_base.hpp new file mode 100644 index 0000000..7dada35 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/timer_queue_base.hpp @@ -0,0 +1,65 @@ +// +// detail/timer_queue_base.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_TIMER_QUEUE_BASE_HPP +#define ASIO_DETAIL_TIMER_QUEUE_BASE_HPP + + +#include "asio/detail/config.hpp" +#include "asio/detail/noncopyable.hpp" +#include "asio/detail/op_queue.hpp" +#include "asio/detail/operation.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class timer_queue_base + : private noncopyable +{ +public: + // Constructor. + timer_queue_base() : next_(0) {} + + // Destructor. + virtual ~timer_queue_base() {} + + // Whether there are no timers in the queue. + virtual bool empty() const = 0; + + // Get the time to wait until the next timer. + virtual long wait_duration_msec(long max_duration) const = 0; + + // Get the time to wait until the next timer. + virtual long wait_duration_usec(long max_duration) const = 0; + + // Dequeue all ready timers. + virtual void get_ready_timers(op_queue<operation>& ops) = 0; + + // Dequeue all timers. + virtual void get_all_timers(op_queue<operation>& ops) = 0; + +private: + friend class timer_queue_set; + + // Next timer queue in the set. + timer_queue_base* next_; +}; + +template <typename Time_Traits> +class timer_queue; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_TIMER_QUEUE_BASE_HPP diff --git a/asio-1.10.6/include/asio/detail/timer_queue_set.hpp b/asio-1.10.6/include/asio/detail/timer_queue_set.hpp new file mode 100644 index 0000000..58ce356 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/timer_queue_set.hpp @@ -0,0 +1,61 @@ +// +// detail/timer_queue_set.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_TIMER_QUEUE_SET_HPP +#define ASIO_DETAIL_TIMER_QUEUE_SET_HPP + + +#include "asio/detail/config.hpp" +#include "asio/detail/timer_queue_base.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class timer_queue_set +{ +public: + // Constructor. + ASIO_DECL timer_queue_set(); + + // Add a timer queue to the set. + ASIO_DECL void insert(timer_queue_base* q); + + // Remove a timer queue from the set. + ASIO_DECL void erase(timer_queue_base* q); + + // Determine whether all queues are empty. + ASIO_DECL bool all_empty() const; + + // Get the wait duration in milliseconds. + ASIO_DECL long wait_duration_msec(long max_duration) const; + + // Get the wait duration in microseconds. + ASIO_DECL long wait_duration_usec(long max_duration) const; + + // Dequeue all ready timers. + ASIO_DECL void get_ready_timers(op_queue<operation>& ops); + + // Dequeue all timers. + ASIO_DECL void get_all_timers(op_queue<operation>& ops); + +private: + timer_queue_base* first_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +# include "asio/detail/impl/timer_queue_set.ipp" + +#endif // ASIO_DETAIL_TIMER_QUEUE_SET_HPP diff --git a/asio-1.10.6/include/asio/detail/tss_ptr.hpp b/asio-1.10.6/include/asio/detail/tss_ptr.hpp new file mode 100644 index 0000000..4562421 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/tss_ptr.hpp @@ -0,0 +1,54 @@ +// +// detail/tss_ptr.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_TSS_PTR_HPP +#define ASIO_DETAIL_TSS_PTR_HPP + + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_THREAD_KEYWORD_EXTENSION) +# include "asio/detail/keyword_tss_ptr.hpp" +#elif defined(ASIO_HAS_PTHREADS) +# include "asio/detail/posix_tss_ptr.hpp" +#else +# error Only Windows and POSIX are supported! +#endif + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename T> +class tss_ptr +#if defined(ASIO_HAS_THREAD_KEYWORD_EXTENSION) + : public keyword_tss_ptr<T> +#elif defined(ASIO_HAS_PTHREADS) + : public posix_tss_ptr<T> +#endif +{ +public: + void operator=(T* value) + { +#if defined(ASIO_HAS_THREAD_KEYWORD_EXTENSION) + keyword_tss_ptr<T>::operator=(value); +#elif defined(ASIO_HAS_PTHREADS) + posix_tss_ptr<T>::operator=(value); +#endif + } +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_TSS_PTR_HPP diff --git a/asio-1.10.6/include/asio/detail/type_traits.hpp b/asio-1.10.6/include/asio/detail/type_traits.hpp new file mode 100644 index 0000000..fd9adfd --- /dev/null +++ b/asio-1.10.6/include/asio/detail/type_traits.hpp @@ -0,0 +1,32 @@ +// +// detail/type_traits.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_TYPE_TRAITS_HPP +#define ASIO_DETAIL_TYPE_TRAITS_HPP + + +#include "asio/detail/config.hpp" + +# include <type_traits> + +namespace asio { + +using std::add_const; +using std::enable_if; +using std::is_const; +using std::is_convertible; +using std::is_function; +using std::is_same; +using std::remove_pointer; +using std::remove_reference; + +} // namespace asio + +#endif // ASIO_DETAIL_TYPE_TRAITS_HPP diff --git a/asio-1.10.6/include/asio/detail/wait_op.hpp b/asio-1.10.6/include/asio/detail/wait_op.hpp new file mode 100644 index 0000000..1c9a5c3 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/wait_op.hpp @@ -0,0 +1,42 @@ +// +// detail/wait_op.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_WAIT_OP_HPP +#define ASIO_DETAIL_WAIT_OP_HPP + + +#include "asio/detail/config.hpp" +#include "asio/detail/operation.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class wait_op + : public operation +{ +public: + // The error code to be passed to the completion handler. + asio::error_code ec_; + +protected: + wait_op(func_type func) + : operation(func) + { + } +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_WAIT_OP_HPP diff --git a/asio-1.10.6/include/asio/detail/weak_ptr.hpp b/asio-1.10.6/include/asio/detail/weak_ptr.hpp new file mode 100644 index 0000000..8bfe158 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/weak_ptr.hpp @@ -0,0 +1,27 @@ +// +// detail/weak_ptr.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_WEAK_PTR_HPP +#define ASIO_DETAIL_WEAK_PTR_HPP + + +#include "asio/detail/config.hpp" + +# include <memory> + +namespace asio { +namespace detail { + +using std::weak_ptr; + +} // namespace detail +} // namespace asio + +#endif // ASIO_DETAIL_WEAK_PTR_HPP diff --git a/asio-1.10.6/include/asio/detail/win_fd_set_adapter.hpp b/asio-1.10.6/include/asio/detail/win_fd_set_adapter.hpp new file mode 100644 index 0000000..db11607 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/win_fd_set_adapter.hpp @@ -0,0 +1,18 @@ +// +// detail/win_fd_set_adapter.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_WIN_FD_SET_ADAPTER_HPP +#define ASIO_DETAIL_WIN_FD_SET_ADAPTER_HPP + + +#include "asio/detail/config.hpp" + + +#endif // ASIO_DETAIL_WIN_FD_SET_ADAPTER_HPP diff --git a/asio-1.10.6/include/asio/detail/winsock_init.hpp b/asio-1.10.6/include/asio/detail/winsock_init.hpp new file mode 100644 index 0000000..eec46b9 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/winsock_init.hpp @@ -0,0 +1,18 @@ +// +// detail/winsock_init.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_WINSOCK_INIT_HPP +#define ASIO_DETAIL_WINSOCK_INIT_HPP + + +#include "asio/detail/config.hpp" + + +#endif // ASIO_DETAIL_WINSOCK_INIT_HPP diff --git a/asio-1.10.6/include/asio/detail/wrapped_handler.hpp b/asio-1.10.6/include/asio/detail/wrapped_handler.hpp new file mode 100644 index 0000000..0d81363 --- /dev/null +++ b/asio-1.10.6/include/asio/detail/wrapped_handler.hpp @@ -0,0 +1,284 @@ +// +// detail/wrapped_handler.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_WRAPPED_HANDLER_HPP +#define ASIO_DETAIL_WRAPPED_HANDLER_HPP + + +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/handler_alloc_helpers.hpp" +#include "asio/detail/handler_cont_helpers.hpp" +#include "asio/detail/handler_invoke_helpers.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +struct is_continuation_delegated +{ + template <typename Dispatcher, typename Handler> + bool operator()(Dispatcher&, Handler& handler) const + { + return asio_handler_cont_helpers::is_continuation(handler); + } +}; + +struct is_continuation_if_running +{ + template <typename Dispatcher, typename Handler> + bool operator()(Dispatcher& dispatcher, Handler&) const + { + return dispatcher.running_in_this_thread(); + } +}; + +template <typename Dispatcher, typename Handler, + typename IsContinuation = is_continuation_delegated> +class wrapped_handler +{ +public: + typedef void result_type; + + wrapped_handler(Dispatcher dispatcher, Handler& handler) + : dispatcher_(dispatcher), + handler_(ASIO_MOVE_CAST(Handler)(handler)) + { + } + + wrapped_handler(const wrapped_handler& other) + : dispatcher_(other.dispatcher_), + handler_(other.handler_) + { + } + + wrapped_handler(wrapped_handler&& other) + : dispatcher_(other.dispatcher_), + handler_(ASIO_MOVE_CAST(Handler)(other.handler_)) + { + } + + void operator()() + { + dispatcher_.dispatch(ASIO_MOVE_CAST(Handler)(handler_)); + } + + void operator()() const + { + dispatcher_.dispatch(handler_); + } + + template <typename Arg1> + void operator()(const Arg1& arg1) + { + dispatcher_.dispatch(detail::bind_handler(handler_, arg1)); + } + + template <typename Arg1> + void operator()(const Arg1& arg1) const + { + dispatcher_.dispatch(detail::bind_handler(handler_, arg1)); + } + + template <typename Arg1, typename Arg2> + void operator()(const Arg1& arg1, const Arg2& arg2) + { + dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2)); + } + + template <typename Arg1, typename Arg2> + void operator()(const Arg1& arg1, const Arg2& arg2) const + { + dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2)); + } + + template <typename Arg1, typename Arg2, typename Arg3> + void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3) + { + dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2, arg3)); + } + + template <typename Arg1, typename Arg2, typename Arg3> + void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3) const + { + dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2, arg3)); + } + + template <typename Arg1, typename Arg2, typename Arg3, typename Arg4> + void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, + const Arg4& arg4) + { + dispatcher_.dispatch( + detail::bind_handler(handler_, arg1, arg2, arg3, arg4)); + } + + template <typename Arg1, typename Arg2, typename Arg3, typename Arg4> + void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, + const Arg4& arg4) const + { + dispatcher_.dispatch( + detail::bind_handler(handler_, arg1, arg2, arg3, arg4)); + } + + template <typename Arg1, typename Arg2, typename Arg3, typename Arg4, + typename Arg5> + void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, + const Arg4& arg4, const Arg5& arg5) + { + dispatcher_.dispatch( + detail::bind_handler(handler_, arg1, arg2, arg3, arg4, arg5)); + } + + template <typename Arg1, typename Arg2, typename Arg3, typename Arg4, + typename Arg5> + void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, + const Arg4& arg4, const Arg5& arg5) const + { + dispatcher_.dispatch( + detail::bind_handler(handler_, arg1, arg2, arg3, arg4, arg5)); + } + +//private: + Dispatcher dispatcher_; + Handler handler_; +}; + +template <typename Handler, typename Context> +class rewrapped_handler +{ +public: + explicit rewrapped_handler(Handler& handler, const Context& context) + : context_(context), + handler_(ASIO_MOVE_CAST(Handler)(handler)) + { + } + + explicit rewrapped_handler(const Handler& handler, const Context& context) + : context_(context), + handler_(handler) + { + } + + rewrapped_handler(const rewrapped_handler& other) + : context_(other.context_), + handler_(other.handler_) + { + } + + rewrapped_handler(rewrapped_handler&& other) + : context_(ASIO_MOVE_CAST(Context)(other.context_)), + handler_(ASIO_MOVE_CAST(Handler)(other.handler_)) + { + } + + void operator()() + { + handler_(); + } + + void operator()() const + { + handler_(); + } + +//private: + Context context_; + Handler handler_; +}; + +template <typename Dispatcher, typename Handler, typename IsContinuation> +inline void* asio_handler_allocate(std::size_t size, + wrapped_handler<Dispatcher, Handler, IsContinuation>* this_handler) +{ + return asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); +} + +template <typename Dispatcher, typename Handler, typename IsContinuation> +inline void asio_handler_deallocate(void* pointer, std::size_t size, + wrapped_handler<Dispatcher, Handler, IsContinuation>* this_handler) +{ + asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); +} + +template <typename Dispatcher, typename Handler, typename IsContinuation> +inline bool asio_handler_is_continuation( + wrapped_handler<Dispatcher, Handler, IsContinuation>* this_handler) +{ + return IsContinuation()(this_handler->dispatcher_, this_handler->handler_); +} + +template <typename Function, typename Dispatcher, + typename Handler, typename IsContinuation> +inline void asio_handler_invoke(Function& function, + wrapped_handler<Dispatcher, Handler, IsContinuation>* this_handler) +{ + this_handler->dispatcher_.dispatch( + rewrapped_handler<Function, Handler>( + function, this_handler->handler_)); +} + +template <typename Function, typename Dispatcher, + typename Handler, typename IsContinuation> +inline void asio_handler_invoke(const Function& function, + wrapped_handler<Dispatcher, Handler, IsContinuation>* this_handler) +{ + this_handler->dispatcher_.dispatch( + rewrapped_handler<Function, Handler>( + function, this_handler->handler_)); +} + +template <typename Handler, typename Context> +inline void* asio_handler_allocate(std::size_t size, + rewrapped_handler<Handler, Context>* this_handler) +{ + return asio_handler_alloc_helpers::allocate( + size, this_handler->context_); +} + +template <typename Handler, typename Context> +inline void asio_handler_deallocate(void* pointer, std::size_t size, + rewrapped_handler<Handler, Context>* this_handler) +{ + asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->context_); +} + +template <typename Dispatcher, typename Context> +inline bool asio_handler_is_continuation( + rewrapped_handler<Dispatcher, Context>* this_handler) +{ + return asio_handler_cont_helpers::is_continuation( + this_handler->context_); +} + +template <typename Function, typename Handler, typename Context> +inline void asio_handler_invoke(Function& function, + rewrapped_handler<Handler, Context>* this_handler) +{ + asio_handler_invoke_helpers::invoke( + function, this_handler->context_); +} + +template <typename Function, typename Handler, typename Context> +inline void asio_handler_invoke(const Function& function, + rewrapped_handler<Handler, Context>* this_handler) +{ + asio_handler_invoke_helpers::invoke( + function, this_handler->context_); +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_WRAPPED_HANDLER_HPP diff --git a/asio-1.10.6/include/asio/error.hpp b/asio-1.10.6/include/asio/error.hpp new file mode 100644 index 0000000..8361e46 --- /dev/null +++ b/asio-1.10.6/include/asio/error.hpp @@ -0,0 +1,284 @@ +// +// error.hpp +// ~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_ERROR_HPP +#define ASIO_ERROR_HPP + + +#include "asio/detail/config.hpp" +#include "asio/error_code.hpp" +#include "asio/system_error.hpp" +# include <cerrno> +# include <netdb.h> + +# define ASIO_NATIVE_ERROR(e) e +# define ASIO_SOCKET_ERROR(e) e +# define ASIO_NETDB_ERROR(e) e +# define ASIO_GETADDRINFO_ERROR(e) e +# define ASIO_WIN_OR_POSIX(e_win, e_posix) e_posix + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace error { + +enum basic_errors +{ + /// Permission denied. + access_denied = ASIO_SOCKET_ERROR(EACCES), + + /// Address family not supported by protocol. + address_family_not_supported = ASIO_SOCKET_ERROR(EAFNOSUPPORT), + + /// Address already in use. + address_in_use = ASIO_SOCKET_ERROR(EADDRINUSE), + + /// Transport endpoint is already connected. + already_connected = ASIO_SOCKET_ERROR(EISCONN), + + /// Operation already in progress. + already_started = ASIO_SOCKET_ERROR(EALREADY), + + /// Broken pipe. + broken_pipe = ASIO_WIN_OR_POSIX( + ASIO_NATIVE_ERROR(ERROR_BROKEN_PIPE), + ASIO_NATIVE_ERROR(EPIPE)), + + /// A connection has been aborted. + connection_aborted = ASIO_SOCKET_ERROR(ECONNABORTED), + + /// Connection refused. + connection_refused = ASIO_SOCKET_ERROR(ECONNREFUSED), + + /// Connection reset by peer. + connection_reset = ASIO_SOCKET_ERROR(ECONNRESET), + + /// Bad file descriptor. + bad_descriptor = ASIO_SOCKET_ERROR(EBADF), + + /// Bad address. + fault = ASIO_SOCKET_ERROR(EFAULT), + + /// No route to host. + host_unreachable = ASIO_SOCKET_ERROR(EHOSTUNREACH), + + /// Operation now in progress. + in_progress = ASIO_SOCKET_ERROR(EINPROGRESS), + + /// Interrupted system call. + interrupted = ASIO_SOCKET_ERROR(EINTR), + + /// Invalid argument. + invalid_argument = ASIO_SOCKET_ERROR(EINVAL), + + /// Message too long. + message_size = ASIO_SOCKET_ERROR(EMSGSIZE), + + /// The name was too long. + name_too_long = ASIO_SOCKET_ERROR(ENAMETOOLONG), + + /// Network is down. + network_down = ASIO_SOCKET_ERROR(ENETDOWN), + + /// Network dropped connection on reset. + network_reset = ASIO_SOCKET_ERROR(ENETRESET), + + /// Network is unreachable. + network_unreachable = ASIO_SOCKET_ERROR(ENETUNREACH), + + /// Too many open files. + no_descriptors = ASIO_SOCKET_ERROR(EMFILE), + + /// No buffer space available. + no_buffer_space = ASIO_SOCKET_ERROR(ENOBUFS), + + /// Cannot allocate memory. + no_memory = ASIO_WIN_OR_POSIX( + ASIO_NATIVE_ERROR(ERROR_OUTOFMEMORY), + ASIO_NATIVE_ERROR(ENOMEM)), + + /// Operation not permitted. + no_permission = ASIO_WIN_OR_POSIX( + ASIO_NATIVE_ERROR(ERROR_ACCESS_DENIED), + ASIO_NATIVE_ERROR(EPERM)), + + /// Protocol not available. + no_protocol_option = ASIO_SOCKET_ERROR(ENOPROTOOPT), + + /// No such device. + no_such_device = ASIO_WIN_OR_POSIX( + ASIO_NATIVE_ERROR(ERROR_BAD_UNIT), + ASIO_NATIVE_ERROR(ENODEV)), + + /// Transport endpoint is not connected. + not_connected = ASIO_SOCKET_ERROR(ENOTCONN), + + /// Socket operation on non-socket. + not_socket = ASIO_SOCKET_ERROR(ENOTSOCK), + + /// Operation cancelled. + operation_aborted = ASIO_WIN_OR_POSIX( + ASIO_NATIVE_ERROR(ERROR_OPERATION_ABORTED), + ASIO_NATIVE_ERROR(ECANCELED)), + + /// Operation not supported. + operation_not_supported = ASIO_SOCKET_ERROR(EOPNOTSUPP), + + /// Cannot send after transport endpoint shutdown. + shut_down = ASIO_SOCKET_ERROR(ESHUTDOWN), + + /// Connection timed out. + timed_out = ASIO_SOCKET_ERROR(ETIMEDOUT), + + /// Resource temporarily unavailable. + try_again = ASIO_WIN_OR_POSIX( + ASIO_NATIVE_ERROR(ERROR_RETRY), + ASIO_NATIVE_ERROR(EAGAIN)), + + /// The socket is marked non-blocking and the requested operation would block. + would_block = ASIO_SOCKET_ERROR(EWOULDBLOCK) +}; + +enum netdb_errors +{ + /// Host not found (authoritative). + host_not_found = ASIO_NETDB_ERROR(HOST_NOT_FOUND), + + /// Host not found (non-authoritative). + host_not_found_try_again = ASIO_NETDB_ERROR(TRY_AGAIN), + + /// The query is valid but does not have associated address data. + no_data = ASIO_NETDB_ERROR(NO_DATA), + + /// A non-recoverable error occurred. + no_recovery = ASIO_NETDB_ERROR(NO_RECOVERY) +}; + +enum addrinfo_errors +{ + /// The service is not supported for the given socket type. + service_not_found = ASIO_WIN_OR_POSIX( + ASIO_NATIVE_ERROR(WSATYPE_NOT_FOUND), + ASIO_GETADDRINFO_ERROR(EAI_SERVICE)), + + /// The socket type is not supported. + socket_type_not_supported = ASIO_WIN_OR_POSIX( + ASIO_NATIVE_ERROR(WSAESOCKTNOSUPPORT), + ASIO_GETADDRINFO_ERROR(EAI_SOCKTYPE)) +}; + +enum misc_errors +{ + /// Already open. + already_open = 1, + + /// End of file or stream. + eof, + + /// Element not found. + not_found, + + /// The descriptor cannot fit into the select system call's fd_set. + fd_set_failure +}; + +inline const asio::error_category& get_system_category() +{ + return asio::system_category(); +} + + +extern ASIO_DECL +const asio::error_category& get_netdb_category(); + +extern ASIO_DECL +const asio::error_category& get_addrinfo_category(); + + +extern ASIO_DECL +const asio::error_category& get_misc_category(); + +static const asio::error_category& system_category + = asio::error::get_system_category(); +static const asio::error_category& netdb_category + = asio::error::get_netdb_category(); +static const asio::error_category& addrinfo_category + = asio::error::get_addrinfo_category(); +static const asio::error_category& misc_category + = asio::error::get_misc_category(); + +} // namespace error +} // namespace asio + +namespace std { + +template<> struct is_error_code_enum<asio::error::basic_errors> +{ + static const bool value = true; +}; + +template<> struct is_error_code_enum<asio::error::netdb_errors> +{ + static const bool value = true; +}; + +template<> struct is_error_code_enum<asio::error::addrinfo_errors> +{ + static const bool value = true; +}; + +template<> struct is_error_code_enum<asio::error::misc_errors> +{ + static const bool value = true; +}; + +} // namespace std + +namespace asio { +namespace error { + +inline asio::error_code make_error_code(basic_errors e) +{ + return asio::error_code( + static_cast<int>(e), get_system_category()); +} + +inline asio::error_code make_error_code(netdb_errors e) +{ + return asio::error_code( + static_cast<int>(e), get_netdb_category()); +} + +inline asio::error_code make_error_code(addrinfo_errors e) +{ + return asio::error_code( + static_cast<int>(e), get_addrinfo_category()); +} + +inline asio::error_code make_error_code(misc_errors e) +{ + return asio::error_code( + static_cast<int>(e), get_misc_category()); +} + +} // namespace error +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#undef ASIO_NATIVE_ERROR +#undef ASIO_SOCKET_ERROR +#undef ASIO_NETDB_ERROR +#undef ASIO_GETADDRINFO_ERROR +#undef ASIO_WIN_OR_POSIX + +# include "asio/impl/error.ipp" + +#endif // ASIO_ERROR_HPP diff --git a/asio-1.10.6/include/asio/error_code.hpp b/asio-1.10.6/include/asio/error_code.hpp new file mode 100644 index 0000000..bf3001c --- /dev/null +++ b/asio-1.10.6/include/asio/error_code.hpp @@ -0,0 +1,40 @@ +// +// error_code.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_ERROR_CODE_HPP +#define ASIO_ERROR_CODE_HPP + + +#include "asio/detail/config.hpp" + +# include <system_error> + +#include "asio/detail/push_options.hpp" + +namespace asio { + + +typedef std::error_category error_category; + + +/// Returns the error category used for the system errors produced by asio. +extern ASIO_DECL const error_category& system_category(); + + +typedef std::error_code error_code; + + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +# include "asio/impl/error_code.ipp" + +#endif // ASIO_ERROR_CODE_HPP diff --git a/asio-1.10.6/include/asio/handler_alloc_hook.hpp b/asio-1.10.6/include/asio/handler_alloc_hook.hpp new file mode 100644 index 0000000..c2d0146 --- /dev/null +++ b/asio-1.10.6/include/asio/handler_alloc_hook.hpp @@ -0,0 +1,76 @@ +// +// handler_alloc_hook.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_HANDLER_ALLOC_HOOK_HPP +#define ASIO_HANDLER_ALLOC_HOOK_HPP + + +#include "asio/detail/config.hpp" +#include <cstddef> + +#include "asio/detail/push_options.hpp" + +namespace asio { + +/// Default allocation function for handlers. +/** + * Asynchronous operations may need to allocate temporary objects. Since + * asynchronous operations have a handler function object, these temporary + * objects can be said to be associated with the handler. + * + * Implement asio_handler_allocate and asio_handler_deallocate for your own + * handlers to provide custom allocation for these temporary objects. + * + * The default implementation of these allocation hooks uses <tt>::operator + * new</tt> and <tt>::operator delete</tt>. + * + * @note All temporary objects associated with a handler will be deallocated + * before the upcall to the handler is performed. This allows the same memory to + * be reused for a subsequent asynchronous operation initiated by the handler. + * + * @par Example + * @code + * class my_handler; + * + * void* asio_handler_allocate(std::size_t size, my_handler* context) + * { + * return ::operator new(size); + * } + * + * void asio_handler_deallocate(void* pointer, std::size_t size, + * my_handler* context) + * { + * ::operator delete(pointer); + * } + * @endcode + */ +ASIO_DECL void* asio_handler_allocate( + std::size_t size, ...); + +/// Default deallocation function for handlers. +/** + * Implement asio_handler_allocate and asio_handler_deallocate for your own + * handlers to provide custom allocation for the associated temporary objects. + * + * The default implementation of these allocation hooks uses <tt>::operator + * new</tt> and <tt>::operator delete</tt>. + * + * @sa asio_handler_allocate. + */ +ASIO_DECL void asio_handler_deallocate( + void* pointer, std::size_t size, ...); + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +# include "asio/impl/handler_alloc_hook.ipp" + +#endif // ASIO_HANDLER_ALLOC_HOOK_HPP diff --git a/asio-1.10.6/include/asio/handler_continuation_hook.hpp b/asio-1.10.6/include/asio/handler_continuation_hook.hpp new file mode 100644 index 0000000..b4f721c --- /dev/null +++ b/asio-1.10.6/include/asio/handler_continuation_hook.hpp @@ -0,0 +1,51 @@ +// +// handler_continuation_hook.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_HANDLER_CONTINUATION_HOOK_HPP +#define ASIO_HANDLER_CONTINUATION_HOOK_HPP + + +#include "asio/detail/config.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +/// Default continuation function for handlers. +/** + * Asynchronous operations may represent a continuation of the asynchronous + * control flow associated with the current handler. The implementation can use + * this knowledge to optimise scheduling of the handler. + * + * Implement asio_handler_is_continuation for your own handlers to indicate + * when a handler represents a continuation. + * + * The default implementation of the continuation hook returns <tt>false</tt>. + * + * @par Example + * @code + * class my_handler; + * + * bool asio_handler_is_continuation(my_handler* context) + * { + * return true; + * } + * @endcode + */ +inline bool asio_handler_is_continuation(...) +{ + return false; +} + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_HANDLER_CONTINUATION_HOOK_HPP diff --git a/asio-1.10.6/include/asio/handler_invoke_hook.hpp b/asio-1.10.6/include/asio/handler_invoke_hook.hpp new file mode 100644 index 0000000..8f3d219 --- /dev/null +++ b/asio-1.10.6/include/asio/handler_invoke_hook.hpp @@ -0,0 +1,82 @@ +// +// handler_invoke_hook.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_HANDLER_INVOKE_HOOK_HPP +#define ASIO_HANDLER_INVOKE_HOOK_HPP + + +#include "asio/detail/config.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +/** @defgroup asio_handler_invoke asio::asio_handler_invoke + * + * @brief Default invoke function for handlers. + * + * Completion handlers for asynchronous operations are invoked by the + * io_service associated with the corresponding object (e.g. a socket or + * deadline_timer). Certain guarantees are made on when the handler may be + * invoked, in particular that a handler can only be invoked from a thread that + * is currently calling @c run() on the corresponding io_service object. + * Handlers may subsequently be invoked through other objects (such as + * io_service::strand objects) that provide additional guarantees. + * + * When asynchronous operations are composed from other asynchronous + * operations, all intermediate handlers should be invoked using the same + * method as the final handler. This is required to ensure that user-defined + * objects are not accessed in a way that may violate the guarantees. This + * hooking function ensures that the invoked method used for the final handler + * is accessible at each intermediate step. + * + * Implement asio_handler_invoke for your own handlers to specify a custom + * invocation strategy. + * + * This default implementation invokes the function object like so: + * @code function(); @endcode + * If necessary, the default implementation makes a copy of the function object + * so that the non-const operator() can be used. + * + * @par Example + * @code + * class my_handler; + * + * template <typename Function> + * void asio_handler_invoke(Function function, my_handler* context) + * { + * context->strand_.dispatch(function); + * } + * @endcode + */ +/*@{*/ + +/// Default handler invocation hook used for non-const function objects. +template <typename Function> +inline void asio_handler_invoke(Function& function, ...) +{ + function(); +} + +/// Default handler invocation hook used for const function objects. +template <typename Function> +inline void asio_handler_invoke(const Function& function, ...) +{ + Function tmp(function); + tmp(); +} + +/*@}*/ + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_HANDLER_INVOKE_HOOK_HPP diff --git a/asio-1.10.6/include/asio/handler_type.hpp b/asio-1.10.6/include/asio/handler_type.hpp new file mode 100644 index 0000000..9c9f1be --- /dev/null +++ b/asio-1.10.6/include/asio/handler_type.hpp @@ -0,0 +1,104 @@ +// +// handler_type.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_HANDLER_TYPE_HPP +#define ASIO_HANDLER_TYPE_HPP + + +#include "asio/detail/config.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +/// Default handler type traits provided for all handlers. +/** + * The handler_type traits class is used for determining the concrete handler + * type to be used for an asynchronous operation. It allows the handler type to + * be determined at the point where the specific completion handler signature + * is known. + * + * This template may be specialised for user-defined handler types. + */ +template <typename Handler, typename Signature> +struct handler_type +{ + /// The handler type for the specific signature. + typedef Handler type; +}; + + +template <typename Handler, typename Signature> +struct handler_type<const Handler, Signature> + : handler_type<Handler, Signature> {}; + +template <typename Handler, typename Signature> +struct handler_type<volatile Handler, Signature> + : handler_type<Handler, Signature> {}; + +template <typename Handler, typename Signature> +struct handler_type<const volatile Handler, Signature> + : handler_type<Handler, Signature> {}; + +template <typename Handler, typename Signature> +struct handler_type<const Handler&, Signature> + : handler_type<Handler, Signature> {}; + +template <typename Handler, typename Signature> +struct handler_type<volatile Handler&, Signature> + : handler_type<Handler, Signature> {}; + +template <typename Handler, typename Signature> +struct handler_type<const volatile Handler&, Signature> + : handler_type<Handler, Signature> {}; + +template <typename Handler, typename Signature> +struct handler_type<Handler&, Signature> + : handler_type<Handler, Signature> {}; + +template <typename Handler, typename Signature> +struct handler_type<Handler&&, Signature> + : handler_type<Handler, Signature> {}; + +template <typename ReturnType, typename Signature> +struct handler_type<ReturnType(), Signature> + : handler_type<ReturnType(*)(), Signature> {}; + +template <typename ReturnType, typename Arg1, typename Signature> +struct handler_type<ReturnType(Arg1), Signature> + : handler_type<ReturnType(*)(Arg1), Signature> {}; + +template <typename ReturnType, typename Arg1, typename Arg2, typename Signature> +struct handler_type<ReturnType(Arg1, Arg2), Signature> + : handler_type<ReturnType(*)(Arg1, Arg2), Signature> {}; + +template <typename ReturnType, typename Arg1, typename Arg2, typename Arg3, + typename Signature> +struct handler_type<ReturnType(Arg1, Arg2, Arg3), Signature> + : handler_type<ReturnType(*)(Arg1, Arg2, Arg3), Signature> {}; + +template <typename ReturnType, typename Arg1, typename Arg2, typename Arg3, + typename Arg4, typename Signature> +struct handler_type<ReturnType(Arg1, Arg2, Arg3, Arg4), Signature> + : handler_type<ReturnType(*)(Arg1, Arg2, Arg3, Arg4), Signature> {}; + +template <typename ReturnType, typename Arg1, typename Arg2, typename Arg3, + typename Arg4, typename Arg5, typename Signature> +struct handler_type<ReturnType(Arg1, Arg2, Arg3, Arg4, Arg5), Signature> + : handler_type<ReturnType(*)(Arg1, Arg2, Arg3, Arg4, Arg5), Signature> {}; + + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#define ASIO_HANDLER_TYPE(h, sig) typename handler_type<h, sig>::type + +#endif // ASIO_HANDLER_TYPE_HPP diff --git a/asio-1.10.6/include/asio/impl/connect.hpp b/asio-1.10.6/include/asio/impl/connect.hpp new file mode 100644 index 0000000..affba0a --- /dev/null +++ b/asio-1.10.6/include/asio/impl/connect.hpp @@ -0,0 +1,423 @@ +// +// impl/connect.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IMPL_CONNECT_HPP +#define ASIO_IMPL_CONNECT_HPP + + +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/consuming_buffers.hpp" +#include "asio/detail/handler_alloc_helpers.hpp" +#include "asio/detail/handler_cont_helpers.hpp" +#include "asio/detail/handler_invoke_helpers.hpp" +#include "asio/detail/handler_type_requirements.hpp" +#include "asio/detail/throw_error.hpp" +#include "asio/error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +namespace detail +{ + struct default_connect_condition + { + template <typename Iterator> + Iterator operator()(const asio::error_code&, Iterator next) + { + return next; + } + }; +} + +template <typename Protocol, typename SocketService, typename Iterator> +Iterator connect(basic_socket<Protocol, SocketService>& s, Iterator begin) +{ + asio::error_code ec; + Iterator result = connect(s, begin, ec); + asio::detail::throw_error(ec, "connect"); + return result; +} + +template <typename Protocol, typename SocketService, typename Iterator> +inline Iterator connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, asio::error_code& ec) +{ + return connect(s, begin, Iterator(), detail::default_connect_condition(), ec); +} + +template <typename Protocol, typename SocketService, typename Iterator> +Iterator connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, Iterator end) +{ + asio::error_code ec; + Iterator result = connect(s, begin, end, ec); + asio::detail::throw_error(ec, "connect"); + return result; +} + +template <typename Protocol, typename SocketService, typename Iterator> +inline Iterator connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, Iterator end, asio::error_code& ec) +{ + return connect(s, begin, end, detail::default_connect_condition(), ec); +} + +template <typename Protocol, typename SocketService, + typename Iterator, typename ConnectCondition> +Iterator connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, ConnectCondition connect_condition) +{ + asio::error_code ec; + Iterator result = connect(s, begin, connect_condition, ec); + asio::detail::throw_error(ec, "connect"); + return result; +} + +template <typename Protocol, typename SocketService, + typename Iterator, typename ConnectCondition> +inline Iterator connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, ConnectCondition connect_condition, + asio::error_code& ec) +{ + return connect(s, begin, Iterator(), connect_condition, ec); +} + +template <typename Protocol, typename SocketService, + typename Iterator, typename ConnectCondition> +Iterator connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, Iterator end, ConnectCondition connect_condition) +{ + asio::error_code ec; + Iterator result = connect(s, begin, end, connect_condition, ec); + asio::detail::throw_error(ec, "connect"); + return result; +} + +template <typename Protocol, typename SocketService, + typename Iterator, typename ConnectCondition> +Iterator connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, Iterator end, ConnectCondition connect_condition, + asio::error_code& ec) +{ + ec = asio::error_code(); + + for (Iterator iter = begin; iter != end; ++iter) + { + iter = connect_condition(ec, iter); + if (iter != end) + { + s.close(ec); + s.connect(*iter, ec); + if (!ec) + return iter; + } + } + + if (!ec) + ec = asio::error::not_found; + + return end; +} + +namespace detail +{ + // Enable the empty base class optimisation for the connect condition. + template <typename ConnectCondition> + class base_from_connect_condition + { + protected: + explicit base_from_connect_condition( + const ConnectCondition& connect_condition) + : connect_condition_(connect_condition) + { + } + + template <typename Iterator> + void check_condition(const asio::error_code& ec, + Iterator& iter, Iterator& end) + { + if (iter != end) + iter = connect_condition_(ec, static_cast<const Iterator&>(iter)); + } + + private: + ConnectCondition connect_condition_; + }; + + // The default_connect_condition implementation is essentially a no-op. This + // template specialisation lets us eliminate all costs associated with it. + template <> + class base_from_connect_condition<default_connect_condition> + { + protected: + explicit base_from_connect_condition(const default_connect_condition&) + { + } + + template <typename Iterator> + void check_condition(const asio::error_code&, Iterator&, Iterator&) + { + } + }; + + template <typename Protocol, typename SocketService, typename Iterator, + typename ConnectCondition, typename ComposedConnectHandler> + class connect_op : base_from_connect_condition<ConnectCondition> + { + public: + connect_op(basic_socket<Protocol, SocketService>& sock, + const Iterator& begin, const Iterator& end, + const ConnectCondition& connect_condition, + ComposedConnectHandler& handler) + : base_from_connect_condition<ConnectCondition>(connect_condition), + socket_(sock), + iter_(begin), + end_(end), + start_(0), + handler_(ASIO_MOVE_CAST(ComposedConnectHandler)(handler)) + { + } + + connect_op(const connect_op& other) + : base_from_connect_condition<ConnectCondition>(other), + socket_(other.socket_), + iter_(other.iter_), + end_(other.end_), + start_(other.start_), + handler_(other.handler_) + { + } + + connect_op(connect_op&& other) + : base_from_connect_condition<ConnectCondition>(other), + socket_(other.socket_), + iter_(other.iter_), + end_(other.end_), + start_(other.start_), + handler_(ASIO_MOVE_CAST(ComposedConnectHandler)(other.handler_)) + { + } + + void operator()(asio::error_code ec, int start = 0) + { + switch (start_ = start) + { + case 1: + for (;;) + { + this->check_condition(ec, iter_, end_); + + if (iter_ != end_) + { + socket_.close(ec); + socket_.async_connect(*iter_, + ASIO_MOVE_CAST(connect_op)(*this)); + return; + } + + if (start) + { + ec = asio::error::not_found; + socket_.get_io_service().post(detail::bind_handler(*this, ec)); + return; + } + + default: + + if (iter_ == end_) + break; + + if (!socket_.is_open()) + { + ec = asio::error::operation_aborted; + break; + } + + if (!ec) + break; + + ++iter_; + } + + handler_(static_cast<const asio::error_code&>(ec), + static_cast<const Iterator&>(iter_)); + } + } + + //private: + basic_socket<Protocol, SocketService>& socket_; + Iterator iter_; + Iterator end_; + int start_; + ComposedConnectHandler handler_; + }; + + template <typename Protocol, typename SocketService, typename Iterator, + typename ConnectCondition, typename ComposedConnectHandler> + inline void* asio_handler_allocate(std::size_t size, + connect_op<Protocol, SocketService, Iterator, + ConnectCondition, ComposedConnectHandler>* this_handler) + { + return asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); + } + + template <typename Protocol, typename SocketService, typename Iterator, + typename ConnectCondition, typename ComposedConnectHandler> + inline void asio_handler_deallocate(void* pointer, std::size_t size, + connect_op<Protocol, SocketService, Iterator, + ConnectCondition, ComposedConnectHandler>* this_handler) + { + asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); + } + + template <typename Protocol, typename SocketService, typename Iterator, + typename ConnectCondition, typename ComposedConnectHandler> + inline bool asio_handler_is_continuation( + connect_op<Protocol, SocketService, Iterator, + ConnectCondition, ComposedConnectHandler>* this_handler) + { + return asio_handler_cont_helpers::is_continuation( + this_handler->handler_); + } + + template <typename Function, typename Protocol, + typename SocketService, typename Iterator, + typename ConnectCondition, typename ComposedConnectHandler> + inline void asio_handler_invoke(Function& function, + connect_op<Protocol, SocketService, Iterator, + ConnectCondition, ComposedConnectHandler>* this_handler) + { + asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } + + template <typename Function, typename Protocol, + typename SocketService, typename Iterator, + typename ConnectCondition, typename ComposedConnectHandler> + inline void asio_handler_invoke(const Function& function, + connect_op<Protocol, SocketService, Iterator, + ConnectCondition, ComposedConnectHandler>* this_handler) + { + asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } +} // namespace detail + +template <typename Protocol, typename SocketService, + typename Iterator, typename ComposedConnectHandler> +inline ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler, + void (asio::error_code, Iterator)) +async_connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, ASIO_MOVE_ARG(ComposedConnectHandler) handler) +{ + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ComposedConnectHandler. + ASIO_COMPOSED_CONNECT_HANDLER_CHECK( + ComposedConnectHandler, handler, Iterator) type_check; + + detail::async_result_init<ComposedConnectHandler, + void (asio::error_code, Iterator)> init( + ASIO_MOVE_CAST(ComposedConnectHandler)(handler)); + + detail::connect_op<Protocol, SocketService, Iterator, + detail::default_connect_condition, ASIO_HANDLER_TYPE( + ComposedConnectHandler, void (asio::error_code, Iterator))>(s, + begin, Iterator(), detail::default_connect_condition(), init.handler)( + asio::error_code(), 1); + + return init.result.get(); +} + +template <typename Protocol, typename SocketService, + typename Iterator, typename ComposedConnectHandler> +inline ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler, + void (asio::error_code, Iterator)) +async_connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, Iterator end, + ASIO_MOVE_ARG(ComposedConnectHandler) handler) +{ + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ComposedConnectHandler. + ASIO_COMPOSED_CONNECT_HANDLER_CHECK( + ComposedConnectHandler, handler, Iterator) type_check; + + detail::async_result_init<ComposedConnectHandler, + void (asio::error_code, Iterator)> init( + ASIO_MOVE_CAST(ComposedConnectHandler)(handler)); + + detail::connect_op<Protocol, SocketService, Iterator, + detail::default_connect_condition, ASIO_HANDLER_TYPE( + ComposedConnectHandler, void (asio::error_code, Iterator))>(s, + begin, end, detail::default_connect_condition(), init.handler)( + asio::error_code(), 1); + + return init.result.get(); +} + +template <typename Protocol, typename SocketService, typename Iterator, + typename ConnectCondition, typename ComposedConnectHandler> +inline ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler, + void (asio::error_code, Iterator)) +async_connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, ConnectCondition connect_condition, + ASIO_MOVE_ARG(ComposedConnectHandler) handler) +{ + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ComposedConnectHandler. + ASIO_COMPOSED_CONNECT_HANDLER_CHECK( + ComposedConnectHandler, handler, Iterator) type_check; + + detail::async_result_init<ComposedConnectHandler, + void (asio::error_code, Iterator)> init( + ASIO_MOVE_CAST(ComposedConnectHandler)(handler)); + + detail::connect_op<Protocol, SocketService, Iterator, + ConnectCondition, ASIO_HANDLER_TYPE( + ComposedConnectHandler, void (asio::error_code, Iterator))>(s, + begin, Iterator(), connect_condition, init.handler)( + asio::error_code(), 1); + + return init.result.get(); +} + +template <typename Protocol, typename SocketService, typename Iterator, + typename ConnectCondition, typename ComposedConnectHandler> +inline ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler, + void (asio::error_code, Iterator)) +async_connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, Iterator end, ConnectCondition connect_condition, + ASIO_MOVE_ARG(ComposedConnectHandler) handler) +{ + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ComposedConnectHandler. + ASIO_COMPOSED_CONNECT_HANDLER_CHECK( + ComposedConnectHandler, handler, Iterator) type_check; + + detail::async_result_init<ComposedConnectHandler, + void (asio::error_code, Iterator)> init( + ASIO_MOVE_CAST(ComposedConnectHandler)(handler)); + + detail::connect_op<Protocol, SocketService, Iterator, + ConnectCondition, ASIO_HANDLER_TYPE( + ComposedConnectHandler, void (asio::error_code, Iterator))>(s, + begin, end, connect_condition, init.handler)( + asio::error_code(), 1); + + return init.result.get(); +} + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IMPL_CONNECT_HPP diff --git a/asio-1.10.6/include/asio/impl/error.ipp b/asio-1.10.6/include/asio/impl/error.ipp new file mode 100644 index 0000000..fa05864 --- /dev/null +++ b/asio-1.10.6/include/asio/impl/error.ipp @@ -0,0 +1,123 @@ +// +// impl/error.ipp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IMPL_ERROR_IPP +#define ASIO_IMPL_ERROR_IPP + + +#include "asio/detail/config.hpp" +#include <string> +#include "asio/error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace error { + + +namespace detail { + +class netdb_category : public asio::error_category +{ +public: + const char* name() const ASIO_ERROR_CATEGORY_NOEXCEPT + { + return "asio.netdb"; + } + + std::string message(int value) const + { + if (value == error::host_not_found) + return "Host not found (authoritative)"; + if (value == error::host_not_found_try_again) + return "Host not found (non-authoritative), try again later"; + if (value == error::no_data) + return "The query is valid, but it does not have associated data"; + if (value == error::no_recovery) + return "A non-recoverable error occurred during database lookup"; + return "asio.netdb error"; + } +}; + +} // namespace detail + +const asio::error_category& get_netdb_category() +{ + static detail::netdb_category instance; + return instance; +} + +namespace detail { + +class addrinfo_category : public asio::error_category +{ +public: + const char* name() const ASIO_ERROR_CATEGORY_NOEXCEPT + { + return "asio.addrinfo"; + } + + std::string message(int value) const + { + if (value == error::service_not_found) + return "Service not found"; + if (value == error::socket_type_not_supported) + return "Socket type not supported"; + return "asio.addrinfo error"; + } +}; + +} // namespace detail + +const asio::error_category& get_addrinfo_category() +{ + static detail::addrinfo_category instance; + return instance; +} + + +namespace detail { + +class misc_category : public asio::error_category +{ +public: + const char* name() const ASIO_ERROR_CATEGORY_NOEXCEPT + { + return "asio.misc"; + } + + std::string message(int value) const + { + if (value == error::already_open) + return "Already open"; + if (value == error::eof) + return "End of file"; + if (value == error::not_found) + return "Element not found"; + if (value == error::fd_set_failure) + return "The descriptor does not fit into the select call's fd_set"; + return "asio.misc error"; + } +}; + +} // namespace detail + +const asio::error_category& get_misc_category() +{ + static detail::misc_category instance; + return instance; +} + +} // namespace error +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IMPL_ERROR_IPP diff --git a/asio-1.10.6/include/asio/impl/error_code.ipp b/asio-1.10.6/include/asio/impl/error_code.ipp new file mode 100644 index 0000000..4704245 --- /dev/null +++ b/asio-1.10.6/include/asio/impl/error_code.ipp @@ -0,0 +1,69 @@ +// +// impl/error_code.ipp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IMPL_ERROR_CODE_IPP +#define ASIO_IMPL_ERROR_CODE_IPP + + +#include "asio/detail/config.hpp" +# include <cerrno> +# include <cstring> +# include <string> +#include "asio/detail/local_free_on_block_exit.hpp" +#include "asio/detail/socket_types.hpp" +#include "asio/error_code.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class system_category : public error_category +{ +public: + const char* name() const ASIO_ERROR_CATEGORY_NOEXCEPT + { + return "asio.system"; + } + + std::string message(int value) const + { +#if !defined(__sun) + if (value == ECANCELED) + return "Operation aborted."; +#endif // !defined(__sun) +#if defined(__sun) || defined(__QNX__) || defined(__SYMBIAN32__) + using namespace std; + return strerror(value); +#elif defined(__MACH__) && defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(_AIX) || defined(__hpux) || defined(__osf__) || defined(__ANDROID__) + char buf[256] = ""; + using namespace std; + strerror_r(value, buf, sizeof(buf)); + return buf; +#else + char buf[256] = ""; + return strerror_r(value, buf, sizeof(buf)); +#endif + } +}; + +} // namespace detail + +const error_category& system_category() +{ + static detail::system_category instance; + return instance; +} + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IMPL_ERROR_CODE_IPP diff --git a/asio-1.10.6/include/asio/impl/handler_alloc_hook.ipp b/asio-1.10.6/include/asio/impl/handler_alloc_hook.ipp new file mode 100644 index 0000000..c7efa93 --- /dev/null +++ b/asio-1.10.6/include/asio/impl/handler_alloc_hook.ipp @@ -0,0 +1,57 @@ +// +// impl/handler_alloc_hook.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IMPL_HANDLER_ALLOC_HOOK_IPP +#define ASIO_IMPL_HANDLER_ALLOC_HOOK_IPP + + +#include "asio/detail/config.hpp" +#include "asio/detail/call_stack.hpp" +#include "asio/handler_alloc_hook.hpp" + +#if !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) +# include "asio/detail/task_io_service_thread_info.hpp" +#endif // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) + +#include "asio/detail/push_options.hpp" + +namespace asio { + + +void* asio_handler_allocate(std::size_t size, ...) +{ +#if !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) + typedef detail::task_io_service io_service_impl; + typedef detail::task_io_service_thread_info thread_info; + typedef detail::call_stack<io_service_impl, thread_info> call_stack; + return thread_info::allocate(call_stack::top(), size); +#else // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) + return ::operator new(size); +#endif // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) +} + +void asio_handler_deallocate(void* pointer, std::size_t size, ...) +{ +#if !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) + typedef detail::task_io_service io_service_impl; + typedef detail::task_io_service_thread_info thread_info; + typedef detail::call_stack<io_service_impl, thread_info> call_stack; + thread_info::deallocate(call_stack::top(), pointer, size); +#else // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) + (void)size; + ::operator delete(pointer); +#endif // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) +} + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IMPL_HANDLER_ALLOC_HOOK_IPP diff --git a/asio-1.10.6/include/asio/impl/io_service.hpp b/asio-1.10.6/include/asio/impl/io_service.hpp new file mode 100644 index 0000000..de7265e --- /dev/null +++ b/asio-1.10.6/include/asio/impl/io_service.hpp @@ -0,0 +1,141 @@ +// +// impl/io_service.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IMPL_IO_SERVICE_HPP +#define ASIO_IMPL_IO_SERVICE_HPP + + +#include "asio/detail/handler_type_requirements.hpp" +#include "asio/detail/service_registry.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +template <typename Service> +inline Service& use_service(io_service& ios) +{ + // Check that Service meets the necessary type requirements. + (void)static_cast<io_service::service*>(static_cast<Service*>(0)); + (void)static_cast<const io_service::id*>(&Service::id); + + return ios.service_registry_->template use_service<Service>(); +} + +template <> +inline detail::io_service_impl& use_service<detail::io_service_impl>( + io_service& ios) +{ + return ios.impl_; +} + +template <typename Service> +inline void add_service(io_service& ios, Service* svc) +{ + // Check that Service meets the necessary type requirements. + (void)static_cast<io_service::service*>(static_cast<Service*>(0)); + (void)static_cast<const io_service::id*>(&Service::id); + + ios.service_registry_->template add_service<Service>(svc); +} + +template <typename Service> +inline bool has_service(io_service& ios) +{ + // Check that Service meets the necessary type requirements. + (void)static_cast<io_service::service*>(static_cast<Service*>(0)); + (void)static_cast<const io_service::id*>(&Service::id); + + return ios.service_registry_->template has_service<Service>(); +} + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +# include "asio/detail/task_io_service.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +template <typename CompletionHandler> +inline ASIO_INITFN_RESULT_TYPE(CompletionHandler, void ()) +io_service::dispatch(ASIO_MOVE_ARG(CompletionHandler) handler) +{ + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a CompletionHandler. + ASIO_COMPLETION_HANDLER_CHECK(CompletionHandler, handler) type_check; + + detail::async_result_init< + CompletionHandler, void ()> init( + ASIO_MOVE_CAST(CompletionHandler)(handler)); + + impl_.dispatch(init.handler); + + return init.result.get(); +} + +template <typename CompletionHandler> +inline ASIO_INITFN_RESULT_TYPE(CompletionHandler, void ()) +io_service::post(ASIO_MOVE_ARG(CompletionHandler) handler) +{ + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a CompletionHandler. + ASIO_COMPLETION_HANDLER_CHECK(CompletionHandler, handler) type_check; + + detail::async_result_init< + CompletionHandler, void ()> init( + ASIO_MOVE_CAST(CompletionHandler)(handler)); + + impl_.post(init.handler); + + return init.result.get(); +} + +template <typename Handler> +inline detail::wrapped_handler<io_service&, Handler> +io_service::wrap(Handler handler) +{ + return detail::wrapped_handler<io_service&, Handler>(*this, handler); +} + +inline io_service::work::work(asio::io_service& io_service) + : io_service_impl_(io_service.impl_) +{ + io_service_impl_.work_started(); +} + +inline io_service::work::work(const work& other) + : io_service_impl_(other.io_service_impl_) +{ + io_service_impl_.work_started(); +} + +inline io_service::work::~work() +{ + io_service_impl_.work_finished(); +} + +inline asio::io_service& io_service::work::get_io_service() +{ + return io_service_impl_.get_io_service(); +} + +inline asio::io_service& io_service::service::get_io_service() +{ + return owner_; +} + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IMPL_IO_SERVICE_HPP diff --git a/asio-1.10.6/include/asio/impl/io_service.ipp b/asio-1.10.6/include/asio/impl/io_service.ipp new file mode 100644 index 0000000..839e21b --- /dev/null +++ b/asio-1.10.6/include/asio/impl/io_service.ipp @@ -0,0 +1,148 @@ +// +// impl/io_service.ipp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IMPL_IO_SERVICE_IPP +#define ASIO_IMPL_IO_SERVICE_IPP + + +#include "asio/detail/config.hpp" +#include "asio/io_service.hpp" +#include "asio/detail/limits.hpp" +#include "asio/detail/scoped_ptr.hpp" +#include "asio/detail/service_registry.hpp" +#include "asio/detail/throw_error.hpp" + +# include "asio/detail/task_io_service.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +io_service::io_service() + : service_registry_(new asio::detail::service_registry( + *this, static_cast<impl_type*>(0), + (std::numeric_limits<std::size_t>::max)())), + impl_(service_registry_->first_service<impl_type>()) +{ +} + +io_service::io_service(std::size_t concurrency_hint) + : service_registry_(new asio::detail::service_registry( + *this, static_cast<impl_type*>(0), concurrency_hint)), + impl_(service_registry_->first_service<impl_type>()) +{ +} + +io_service::~io_service() +{ + delete service_registry_; +} + +std::size_t io_service::run() +{ + asio::error_code ec; + std::size_t s = impl_.run(ec); + asio::detail::throw_error(ec); + return s; +} + +std::size_t io_service::run(asio::error_code& ec) +{ + return impl_.run(ec); +} + +std::size_t io_service::run_one() +{ + asio::error_code ec; + std::size_t s = impl_.run_one(ec); + asio::detail::throw_error(ec); + return s; +} + +std::size_t io_service::run_one(asio::error_code& ec) +{ + return impl_.run_one(ec); +} + +std::size_t io_service::poll() +{ + asio::error_code ec; + std::size_t s = impl_.poll(ec); + asio::detail::throw_error(ec); + return s; +} + +std::size_t io_service::poll(asio::error_code& ec) +{ + return impl_.poll(ec); +} + +std::size_t io_service::poll_one() +{ + asio::error_code ec; + std::size_t s = impl_.poll_one(ec); + asio::detail::throw_error(ec); + return s; +} + +std::size_t io_service::poll_one(asio::error_code& ec) +{ + return impl_.poll_one(ec); +} + +void io_service::stop() +{ + impl_.stop(); +} + +bool io_service::stopped() const +{ + return impl_.stopped(); +} + +void io_service::reset() +{ + impl_.reset(); +} + +void io_service::notify_fork(asio::io_service::fork_event event) +{ + service_registry_->notify_fork(event); +} + +io_service::service::service(asio::io_service& owner) + : owner_(owner), + next_(0) +{ +} + +io_service::service::~service() +{ +} + +void io_service::service::fork_service(asio::io_service::fork_event) +{ +} + +service_already_exists::service_already_exists() + : std::logic_error("Service already exists.") +{ +} + +invalid_service_owner::invalid_service_owner() + : std::logic_error("Invalid service owner.") +{ +} + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IMPL_IO_SERVICE_IPP diff --git a/asio-1.10.6/include/asio/impl/read.hpp b/asio-1.10.6/include/asio/impl/read.hpp new file mode 100644 index 0000000..da36082 --- /dev/null +++ b/asio-1.10.6/include/asio/impl/read.hpp @@ -0,0 +1,502 @@ +// +// impl/read.hpp +// ~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IMPL_READ_HPP +#define ASIO_IMPL_READ_HPP + + +#include <algorithm> +#include "asio/buffer.hpp" +#include "asio/completion_condition.hpp" +#include "asio/detail/array_fwd.hpp" +#include "asio/detail/base_from_completion_cond.hpp" +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/consuming_buffers.hpp" +#include "asio/detail/dependent_type.hpp" +#include "asio/detail/handler_alloc_helpers.hpp" +#include "asio/detail/handler_cont_helpers.hpp" +#include "asio/detail/handler_invoke_helpers.hpp" +#include "asio/detail/handler_type_requirements.hpp" +#include "asio/detail/throw_error.hpp" +#include "asio/error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +template <typename SyncReadStream, typename MutableBufferSequence, + typename CompletionCondition> +std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, + CompletionCondition completion_condition, asio::error_code& ec) +{ + ec = asio::error_code(); + asio::detail::consuming_buffers< + mutable_buffer, MutableBufferSequence> tmp(buffers); + std::size_t total_transferred = 0; + tmp.prepare(detail::adapt_completion_condition_result( + completion_condition(ec, total_transferred))); + while (tmp.begin() != tmp.end()) + { + std::size_t bytes_transferred = s.read_some(tmp, ec); + tmp.consume(bytes_transferred); + total_transferred += bytes_transferred; + tmp.prepare(detail::adapt_completion_condition_result( + completion_condition(ec, total_transferred))); + } + return total_transferred; +} + +template <typename SyncReadStream, typename MutableBufferSequence> +inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers) +{ + asio::error_code ec; + std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec); + asio::detail::throw_error(ec, "read"); + return bytes_transferred; +} + +template <typename SyncReadStream, typename MutableBufferSequence> +inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, + asio::error_code& ec) +{ + return read(s, buffers, transfer_all(), ec); +} + +template <typename SyncReadStream, typename MutableBufferSequence, + typename CompletionCondition> +inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, + CompletionCondition completion_condition) +{ + asio::error_code ec; + std::size_t bytes_transferred = read(s, buffers, completion_condition, ec); + asio::detail::throw_error(ec, "read"); + return bytes_transferred; +} + + +namespace detail +{ + template <typename AsyncReadStream, typename MutableBufferSequence, + typename CompletionCondition, typename ReadHandler> + class read_op + : detail::base_from_completion_cond<CompletionCondition> + { + public: + read_op(AsyncReadStream& stream, const MutableBufferSequence& buffers, + CompletionCondition completion_condition, ReadHandler& handler) + : detail::base_from_completion_cond< + CompletionCondition>(completion_condition), + stream_(stream), + buffers_(buffers), + start_(0), + total_transferred_(0), + handler_(ASIO_MOVE_CAST(ReadHandler)(handler)) + { + } + + read_op(const read_op& other) + : detail::base_from_completion_cond<CompletionCondition>(other), + stream_(other.stream_), + buffers_(other.buffers_), + start_(other.start_), + total_transferred_(other.total_transferred_), + handler_(other.handler_) + { + } + + read_op(read_op&& other) + : detail::base_from_completion_cond<CompletionCondition>(other), + stream_(other.stream_), + buffers_(other.buffers_), + start_(other.start_), + total_transferred_(other.total_transferred_), + handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_)) + { + } + + void operator()(const asio::error_code& ec, + std::size_t bytes_transferred, int start = 0) + { + switch (start_ = start) + { + case 1: + buffers_.prepare(this->check_for_completion(ec, total_transferred_)); + for (;;) + { + stream_.async_read_some(buffers_, + ASIO_MOVE_CAST(read_op)(*this)); + return; default: + total_transferred_ += bytes_transferred; + buffers_.consume(bytes_transferred); + buffers_.prepare(this->check_for_completion(ec, total_transferred_)); + if ((!ec && bytes_transferred == 0) + || buffers_.begin() == buffers_.end()) + break; + } + + handler_(ec, static_cast<const std::size_t&>(total_transferred_)); + } + } + + //private: + AsyncReadStream& stream_; + asio::detail::consuming_buffers< + mutable_buffer, MutableBufferSequence> buffers_; + int start_; + std::size_t total_transferred_; + ReadHandler handler_; + }; + + template <typename AsyncReadStream, + typename CompletionCondition, typename ReadHandler> + class read_op<AsyncReadStream, asio::mutable_buffers_1, + CompletionCondition, ReadHandler> + : detail::base_from_completion_cond<CompletionCondition> + { + public: + read_op(AsyncReadStream& stream, + const asio::mutable_buffers_1& buffers, + CompletionCondition completion_condition, ReadHandler& handler) + : detail::base_from_completion_cond< + CompletionCondition>(completion_condition), + stream_(stream), + buffer_(buffers), + start_(0), + total_transferred_(0), + handler_(ASIO_MOVE_CAST(ReadHandler)(handler)) + { + } + + read_op(const read_op& other) + : detail::base_from_completion_cond<CompletionCondition>(other), + stream_(other.stream_), + buffer_(other.buffer_), + start_(other.start_), + total_transferred_(other.total_transferred_), + handler_(other.handler_) + { + } + + read_op(read_op&& other) + : detail::base_from_completion_cond<CompletionCondition>(other), + stream_(other.stream_), + buffer_(other.buffer_), + start_(other.start_), + total_transferred_(other.total_transferred_), + handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_)) + { + } + + void operator()(const asio::error_code& ec, + std::size_t bytes_transferred, int start = 0) + { + std::size_t n = 0; + switch (start_ = start) + { + case 1: + n = this->check_for_completion(ec, total_transferred_); + for (;;) + { + stream_.async_read_some( + asio::buffer(buffer_ + total_transferred_, n), + ASIO_MOVE_CAST(read_op)(*this)); + return; default: + total_transferred_ += bytes_transferred; + if ((!ec && bytes_transferred == 0) + || (n = this->check_for_completion(ec, total_transferred_)) == 0 + || total_transferred_ == asio::buffer_size(buffer_)) + break; + } + + handler_(ec, static_cast<const std::size_t&>(total_transferred_)); + } + } + + //private: + AsyncReadStream& stream_; + asio::mutable_buffer buffer_; + int start_; + std::size_t total_transferred_; + ReadHandler handler_; + }; + + template <typename AsyncReadStream, typename Elem, + typename CompletionCondition, typename ReadHandler> + class read_op<AsyncReadStream, boost::array<Elem, 2>, + CompletionCondition, ReadHandler> + : detail::base_from_completion_cond<CompletionCondition> + { + public: + read_op(AsyncReadStream& stream, const boost::array<Elem, 2>& buffers, + CompletionCondition completion_condition, ReadHandler& handler) + : detail::base_from_completion_cond< + CompletionCondition>(completion_condition), + stream_(stream), + buffers_(buffers), + start_(0), + total_transferred_(0), + handler_(ASIO_MOVE_CAST(ReadHandler)(handler)) + { + } + + read_op(const read_op& other) + : detail::base_from_completion_cond<CompletionCondition>(other), + stream_(other.stream_), + buffers_(other.buffers_), + start_(other.start_), + total_transferred_(other.total_transferred_), + handler_(other.handler_) + { + } + + read_op(read_op&& other) + : detail::base_from_completion_cond<CompletionCondition>(other), + stream_(other.stream_), + buffers_(other.buffers_), + start_(other.start_), + total_transferred_(other.total_transferred_), + handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_)) + { + } + + void operator()(const asio::error_code& ec, + std::size_t bytes_transferred, int start = 0) + { + typename asio::detail::dependent_type<Elem, + boost::array<asio::mutable_buffer, 2> >::type bufs = {{ + asio::mutable_buffer(buffers_[0]), + asio::mutable_buffer(buffers_[1]) }}; + std::size_t buffer_size0 = asio::buffer_size(bufs[0]); + std::size_t buffer_size1 = asio::buffer_size(bufs[1]); + std::size_t n = 0; + switch (start_ = start) + { + case 1: + n = this->check_for_completion(ec, total_transferred_); + for (;;) + { + bufs[0] = asio::buffer(bufs[0] + total_transferred_, n); + bufs[1] = asio::buffer( + bufs[1] + (total_transferred_ < buffer_size0 + ? 0 : total_transferred_ - buffer_size0), + n - asio::buffer_size(bufs[0])); + stream_.async_read_some(bufs, ASIO_MOVE_CAST(read_op)(*this)); + return; default: + total_transferred_ += bytes_transferred; + if ((!ec && bytes_transferred == 0) + || (n = this->check_for_completion(ec, total_transferred_)) == 0 + || total_transferred_ == buffer_size0 + buffer_size1) + break; + } + + handler_(ec, static_cast<const std::size_t&>(total_transferred_)); + } + } + + //private: + AsyncReadStream& stream_; + boost::array<Elem, 2> buffers_; + int start_; + std::size_t total_transferred_; + ReadHandler handler_; + }; + + + template <typename AsyncReadStream, typename Elem, + typename CompletionCondition, typename ReadHandler> + class read_op<AsyncReadStream, std::array<Elem, 2>, + CompletionCondition, ReadHandler> + : detail::base_from_completion_cond<CompletionCondition> + { + public: + read_op(AsyncReadStream& stream, const std::array<Elem, 2>& buffers, + CompletionCondition completion_condition, ReadHandler& handler) + : detail::base_from_completion_cond< + CompletionCondition>(completion_condition), + stream_(stream), + buffers_(buffers), + start_(0), + total_transferred_(0), + handler_(ASIO_MOVE_CAST(ReadHandler)(handler)) + { + } + + read_op(const read_op& other) + : detail::base_from_completion_cond<CompletionCondition>(other), + stream_(other.stream_), + buffers_(other.buffers_), + start_(other.start_), + total_transferred_(other.total_transferred_), + handler_(other.handler_) + { + } + + read_op(read_op&& other) + : detail::base_from_completion_cond<CompletionCondition>(other), + stream_(other.stream_), + buffers_(other.buffers_), + start_(other.start_), + total_transferred_(other.total_transferred_), + handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_)) + { + } + + void operator()(const asio::error_code& ec, + std::size_t bytes_transferred, int start = 0) + { + typename asio::detail::dependent_type<Elem, + std::array<asio::mutable_buffer, 2> >::type bufs = {{ + asio::mutable_buffer(buffers_[0]), + asio::mutable_buffer(buffers_[1]) }}; + std::size_t buffer_size0 = asio::buffer_size(bufs[0]); + std::size_t buffer_size1 = asio::buffer_size(bufs[1]); + std::size_t n = 0; + switch (start_ = start) + { + case 1: + n = this->check_for_completion(ec, total_transferred_); + for (;;) + { + bufs[0] = asio::buffer(bufs[0] + total_transferred_, n); + bufs[1] = asio::buffer( + bufs[1] + (total_transferred_ < buffer_size0 + ? 0 : total_transferred_ - buffer_size0), + n - asio::buffer_size(bufs[0])); + stream_.async_read_some(bufs, ASIO_MOVE_CAST(read_op)(*this)); + return; default: + total_transferred_ += bytes_transferred; + if ((!ec && bytes_transferred == 0) + || (n = this->check_for_completion(ec, total_transferred_)) == 0 + || total_transferred_ == buffer_size0 + buffer_size1) + break; + } + + handler_(ec, static_cast<const std::size_t&>(total_transferred_)); + } + } + + //private: + AsyncReadStream& stream_; + std::array<Elem, 2> buffers_; + int start_; + std::size_t total_transferred_; + ReadHandler handler_; + }; + + + template <typename AsyncReadStream, typename MutableBufferSequence, + typename CompletionCondition, typename ReadHandler> + inline void* asio_handler_allocate(std::size_t size, + read_op<AsyncReadStream, MutableBufferSequence, + CompletionCondition, ReadHandler>* this_handler) + { + return asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); + } + + template <typename AsyncReadStream, typename MutableBufferSequence, + typename CompletionCondition, typename ReadHandler> + inline void asio_handler_deallocate(void* pointer, std::size_t size, + read_op<AsyncReadStream, MutableBufferSequence, + CompletionCondition, ReadHandler>* this_handler) + { + asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); + } + + template <typename AsyncReadStream, typename MutableBufferSequence, + typename CompletionCondition, typename ReadHandler> + inline bool asio_handler_is_continuation( + read_op<AsyncReadStream, MutableBufferSequence, + CompletionCondition, ReadHandler>* this_handler) + { + return this_handler->start_ == 0 ? true + : asio_handler_cont_helpers::is_continuation( + this_handler->handler_); + } + + template <typename Function, typename AsyncReadStream, + typename MutableBufferSequence, typename CompletionCondition, + typename ReadHandler> + inline void asio_handler_invoke(Function& function, + read_op<AsyncReadStream, MutableBufferSequence, + CompletionCondition, ReadHandler>* this_handler) + { + asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } + + template <typename Function, typename AsyncReadStream, + typename MutableBufferSequence, typename CompletionCondition, + typename ReadHandler> + inline void asio_handler_invoke(const Function& function, + read_op<AsyncReadStream, MutableBufferSequence, + CompletionCondition, ReadHandler>* this_handler) + { + asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } +} // namespace detail + +template <typename AsyncReadStream, typename MutableBufferSequence, + typename CompletionCondition, typename ReadHandler> +inline ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (asio::error_code, std::size_t)) +async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, + CompletionCondition completion_condition, + ASIO_MOVE_ARG(ReadHandler) handler) +{ + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + detail::async_result_init< + ReadHandler, void (asio::error_code, std::size_t)> init( + ASIO_MOVE_CAST(ReadHandler)(handler)); + + detail::read_op<AsyncReadStream, MutableBufferSequence, + CompletionCondition, ASIO_HANDLER_TYPE( + ReadHandler, void (asio::error_code, std::size_t))>( + s, buffers, completion_condition, init.handler)( + asio::error_code(), 0, 1); + + return init.result.get(); +} + +template <typename AsyncReadStream, typename MutableBufferSequence, + typename ReadHandler> +inline ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (asio::error_code, std::size_t)) +async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, + ASIO_MOVE_ARG(ReadHandler) handler) +{ + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + detail::async_result_init< + ReadHandler, void (asio::error_code, std::size_t)> init( + ASIO_MOVE_CAST(ReadHandler)(handler)); + + detail::read_op<AsyncReadStream, MutableBufferSequence, + detail::transfer_all_t, ASIO_HANDLER_TYPE( + ReadHandler, void (asio::error_code, std::size_t))>( + s, buffers, transfer_all(), init.handler)( + asio::error_code(), 0, 1); + + return init.result.get(); +} + + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IMPL_READ_HPP diff --git a/asio-1.10.6/include/asio/impl/write.hpp b/asio-1.10.6/include/asio/impl/write.hpp new file mode 100644 index 0000000..282d0f3 --- /dev/null +++ b/asio-1.10.6/include/asio/impl/write.hpp @@ -0,0 +1,575 @@ +// +// impl/write.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IMPL_WRITE_HPP +#define ASIO_IMPL_WRITE_HPP + + +#include "asio/buffer.hpp" +#include "asio/completion_condition.hpp" +#include "asio/detail/array_fwd.hpp" +#include "asio/detail/base_from_completion_cond.hpp" +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/consuming_buffers.hpp" +#include "asio/detail/dependent_type.hpp" +#include "asio/detail/handler_alloc_helpers.hpp" +#include "asio/detail/handler_cont_helpers.hpp" +#include "asio/detail/handler_invoke_helpers.hpp" +#include "asio/detail/handler_type_requirements.hpp" +#include "asio/detail/throw_error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +template <typename SyncWriteStream, typename ConstBufferSequence, + typename CompletionCondition> +std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, + CompletionCondition completion_condition, asio::error_code& ec) +{ + ec = asio::error_code(); + asio::detail::consuming_buffers< + const_buffer, ConstBufferSequence> tmp(buffers); + std::size_t total_transferred = 0; + tmp.prepare(detail::adapt_completion_condition_result( + completion_condition(ec, total_transferred))); + while (tmp.begin() != tmp.end()) + { + std::size_t bytes_transferred = s.write_some(tmp, ec); + tmp.consume(bytes_transferred); + total_transferred += bytes_transferred; + tmp.prepare(detail::adapt_completion_condition_result( + completion_condition(ec, total_transferred))); + } + return total_transferred; +} + +template <typename SyncWriteStream, typename ConstBufferSequence> +inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers) +{ + asio::error_code ec; + std::size_t bytes_transferred = write(s, buffers, transfer_all(), ec); + asio::detail::throw_error(ec, "write"); + return bytes_transferred; +} + +template <typename SyncWriteStream, typename ConstBufferSequence> +inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, + asio::error_code& ec) +{ + return write(s, buffers, transfer_all(), ec); +} + +template <typename SyncWriteStream, typename ConstBufferSequence, + typename CompletionCondition> +inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, + CompletionCondition completion_condition) +{ + asio::error_code ec; + std::size_t bytes_transferred = write(s, buffers, completion_condition, ec); + asio::detail::throw_error(ec, "write"); + return bytes_transferred; +} + + +namespace detail +{ + template <typename AsyncWriteStream, typename ConstBufferSequence, + typename CompletionCondition, typename WriteHandler> + class write_op + : detail::base_from_completion_cond<CompletionCondition> + { + public: + write_op(AsyncWriteStream& stream, const ConstBufferSequence& buffers, + CompletionCondition completion_condition, WriteHandler& handler) + : detail::base_from_completion_cond< + CompletionCondition>(completion_condition), + stream_(stream), + buffers_(buffers), + start_(0), + total_transferred_(0), + handler_(ASIO_MOVE_CAST(WriteHandler)(handler)) + { + } + + write_op(const write_op& other) + : detail::base_from_completion_cond<CompletionCondition>(other), + stream_(other.stream_), + buffers_(other.buffers_), + start_(other.start_), + total_transferred_(other.total_transferred_), + handler_(other.handler_) + { + } + + write_op(write_op&& other) + : detail::base_from_completion_cond<CompletionCondition>(other), + stream_(other.stream_), + buffers_(other.buffers_), + start_(other.start_), + total_transferred_(other.total_transferred_), + handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_)) + { + } + + void operator()(const asio::error_code& ec, + std::size_t bytes_transferred, int start = 0) + { + switch (start_ = start) + { + case 1: + buffers_.prepare(this->check_for_completion(ec, total_transferred_)); + for (;;) + { + stream_.async_write_some(buffers_, + ASIO_MOVE_CAST(write_op)(*this)); + return; default: + total_transferred_ += bytes_transferred; + buffers_.consume(bytes_transferred); + buffers_.prepare(this->check_for_completion(ec, total_transferred_)); + if ((!ec && bytes_transferred == 0) + || buffers_.begin() == buffers_.end()) + break; + } + + handler_(ec, static_cast<const std::size_t&>(total_transferred_)); + } + } + + //private: + AsyncWriteStream& stream_; + asio::detail::consuming_buffers< + const_buffer, ConstBufferSequence> buffers_; + int start_; + std::size_t total_transferred_; + WriteHandler handler_; + }; + + template <typename AsyncWriteStream, + typename CompletionCondition, typename WriteHandler> + class write_op<AsyncWriteStream, asio::mutable_buffers_1, + CompletionCondition, WriteHandler> + : detail::base_from_completion_cond<CompletionCondition> + { + public: + write_op(AsyncWriteStream& stream, + const asio::mutable_buffers_1& buffers, + CompletionCondition completion_condition, + WriteHandler& handler) + : detail::base_from_completion_cond< + CompletionCondition>(completion_condition), + stream_(stream), + buffer_(buffers), + start_(0), + total_transferred_(0), + handler_(ASIO_MOVE_CAST(WriteHandler)(handler)) + { + } + + write_op(const write_op& other) + : detail::base_from_completion_cond<CompletionCondition>(other), + stream_(other.stream_), + buffer_(other.buffer_), + start_(other.start_), + total_transferred_(other.total_transferred_), + handler_(other.handler_) + { + } + + write_op(write_op&& other) + : detail::base_from_completion_cond<CompletionCondition>(other), + stream_(other.stream_), + buffer_(other.buffer_), + start_(other.start_), + total_transferred_(other.total_transferred_), + handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_)) + { + } + + void operator()(const asio::error_code& ec, + std::size_t bytes_transferred, int start = 0) + { + std::size_t n = 0; + switch (start_ = start) + { + case 1: + n = this->check_for_completion(ec, total_transferred_); + for (;;) + { + stream_.async_write_some( + asio::buffer(buffer_ + total_transferred_, n), + ASIO_MOVE_CAST(write_op)(*this)); + return; default: + total_transferred_ += bytes_transferred; + if ((!ec && bytes_transferred == 0) + || (n = this->check_for_completion(ec, total_transferred_)) == 0 + || total_transferred_ == asio::buffer_size(buffer_)) + break; + } + + handler_(ec, static_cast<const std::size_t&>(total_transferred_)); + } + } + + //private: + AsyncWriteStream& stream_; + asio::mutable_buffer buffer_; + int start_; + std::size_t total_transferred_; + WriteHandler handler_; + }; + + template <typename AsyncWriteStream, + typename CompletionCondition, typename WriteHandler> + class write_op<AsyncWriteStream, asio::const_buffers_1, + CompletionCondition, WriteHandler> + : detail::base_from_completion_cond<CompletionCondition> + { + public: + write_op(AsyncWriteStream& stream, + const asio::const_buffers_1& buffers, + CompletionCondition completion_condition, + WriteHandler& handler) + : detail::base_from_completion_cond< + CompletionCondition>(completion_condition), + stream_(stream), + buffer_(buffers), + start_(0), + total_transferred_(0), + handler_(ASIO_MOVE_CAST(WriteHandler)(handler)) + { + } + + write_op(const write_op& other) + : detail::base_from_completion_cond<CompletionCondition>(other), + stream_(other.stream_), + buffer_(other.buffer_), + start_(other.start_), + total_transferred_(other.total_transferred_), + handler_(other.handler_) + { + } + + write_op(write_op&& other) + : detail::base_from_completion_cond<CompletionCondition>(other), + stream_(other.stream_), + buffer_(other.buffer_), + start_(other.start_), + total_transferred_(other.total_transferred_), + handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_)) + { + } + + void operator()(const asio::error_code& ec, + std::size_t bytes_transferred, int start = 0) + { + std::size_t n = 0; + switch (start_ = start) + { + case 1: + n = this->check_for_completion(ec, total_transferred_); + for (;;) + { + stream_.async_write_some( + asio::buffer(buffer_ + total_transferred_, n), + ASIO_MOVE_CAST(write_op)(*this)); + return; default: + total_transferred_ += bytes_transferred; + if ((!ec && bytes_transferred == 0) + || (n = this->check_for_completion(ec, total_transferred_)) == 0 + || total_transferred_ == asio::buffer_size(buffer_)) + break; + } + + handler_(ec, static_cast<const std::size_t&>(total_transferred_)); + } + } + + //private: + AsyncWriteStream& stream_; + asio::const_buffer buffer_; + int start_; + std::size_t total_transferred_; + WriteHandler handler_; + }; + + template <typename AsyncWriteStream, typename Elem, + typename CompletionCondition, typename WriteHandler> + class write_op<AsyncWriteStream, boost::array<Elem, 2>, + CompletionCondition, WriteHandler> + : detail::base_from_completion_cond<CompletionCondition> + { + public: + write_op(AsyncWriteStream& stream, const boost::array<Elem, 2>& buffers, + CompletionCondition completion_condition, WriteHandler& handler) + : detail::base_from_completion_cond< + CompletionCondition>(completion_condition), + stream_(stream), + buffers_(buffers), + start_(0), + total_transferred_(0), + handler_(ASIO_MOVE_CAST(WriteHandler)(handler)) + { + } + + write_op(const write_op& other) + : detail::base_from_completion_cond<CompletionCondition>(other), + stream_(other.stream_), + buffers_(other.buffers_), + start_(other.start_), + total_transferred_(other.total_transferred_), + handler_(other.handler_) + { + } + + write_op(write_op&& other) + : detail::base_from_completion_cond<CompletionCondition>(other), + stream_(other.stream_), + buffers_(other.buffers_), + start_(other.start_), + total_transferred_(other.total_transferred_), + handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_)) + { + } + + void operator()(const asio::error_code& ec, + std::size_t bytes_transferred, int start = 0) + { + typename asio::detail::dependent_type<Elem, + boost::array<asio::const_buffer, 2> >::type bufs = {{ + asio::const_buffer(buffers_[0]), + asio::const_buffer(buffers_[1]) }}; + std::size_t buffer_size0 = asio::buffer_size(bufs[0]); + std::size_t buffer_size1 = asio::buffer_size(bufs[1]); + std::size_t n = 0; + switch (start_ = start) + { + case 1: + n = this->check_for_completion(ec, total_transferred_); + for (;;) + { + bufs[0] = asio::buffer(bufs[0] + total_transferred_, n); + bufs[1] = asio::buffer( + bufs[1] + (total_transferred_ < buffer_size0 + ? 0 : total_transferred_ - buffer_size0), + n - asio::buffer_size(bufs[0])); + stream_.async_write_some(bufs, ASIO_MOVE_CAST(write_op)(*this)); + return; default: + total_transferred_ += bytes_transferred; + if ((!ec && bytes_transferred == 0) + || (n = this->check_for_completion(ec, total_transferred_)) == 0 + || total_transferred_ == buffer_size0 + buffer_size1) + break; + } + + handler_(ec, static_cast<const std::size_t&>(total_transferred_)); + } + } + + //private: + AsyncWriteStream& stream_; + boost::array<Elem, 2> buffers_; + int start_; + std::size_t total_transferred_; + WriteHandler handler_; + }; + + + template <typename AsyncWriteStream, typename Elem, + typename CompletionCondition, typename WriteHandler> + class write_op<AsyncWriteStream, std::array<Elem, 2>, + CompletionCondition, WriteHandler> + : detail::base_from_completion_cond<CompletionCondition> + { + public: + write_op(AsyncWriteStream& stream, const std::array<Elem, 2>& buffers, + CompletionCondition completion_condition, WriteHandler& handler) + : detail::base_from_completion_cond< + CompletionCondition>(completion_condition), + stream_(stream), + buffers_(buffers), + start_(0), + total_transferred_(0), + handler_(ASIO_MOVE_CAST(WriteHandler)(handler)) + { + } + + write_op(const write_op& other) + : detail::base_from_completion_cond<CompletionCondition>(other), + stream_(other.stream_), + buffers_(other.buffers_), + start_(other.start_), + total_transferred_(other.total_transferred_), + handler_(other.handler_) + { + } + + write_op(write_op&& other) + : detail::base_from_completion_cond<CompletionCondition>(other), + stream_(other.stream_), + buffers_(other.buffers_), + start_(other.start_), + total_transferred_(other.total_transferred_), + handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_)) + { + } + + void operator()(const asio::error_code& ec, + std::size_t bytes_transferred, int start = 0) + { + typename asio::detail::dependent_type<Elem, + std::array<asio::const_buffer, 2> >::type bufs = {{ + asio::const_buffer(buffers_[0]), + asio::const_buffer(buffers_[1]) }}; + std::size_t buffer_size0 = asio::buffer_size(bufs[0]); + std::size_t buffer_size1 = asio::buffer_size(bufs[1]); + std::size_t n = 0; + switch (start_ = start) + { + case 1: + n = this->check_for_completion(ec, total_transferred_); + for (;;) + { + bufs[0] = asio::buffer(bufs[0] + total_transferred_, n); + bufs[1] = asio::buffer( + bufs[1] + (total_transferred_ < buffer_size0 + ? 0 : total_transferred_ - buffer_size0), + n - asio::buffer_size(bufs[0])); + stream_.async_write_some(bufs, ASIO_MOVE_CAST(write_op)(*this)); + return; default: + total_transferred_ += bytes_transferred; + if ((!ec && bytes_transferred == 0) + || (n = this->check_for_completion(ec, total_transferred_)) == 0 + || total_transferred_ == buffer_size0 + buffer_size1) + break; + } + + handler_(ec, static_cast<const std::size_t&>(total_transferred_)); + } + } + + //private: + AsyncWriteStream& stream_; + std::array<Elem, 2> buffers_; + int start_; + std::size_t total_transferred_; + WriteHandler handler_; + }; + + + template <typename AsyncWriteStream, typename ConstBufferSequence, + typename CompletionCondition, typename WriteHandler> + inline void* asio_handler_allocate(std::size_t size, + write_op<AsyncWriteStream, ConstBufferSequence, + CompletionCondition, WriteHandler>* this_handler) + { + return asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); + } + + template <typename AsyncWriteStream, typename ConstBufferSequence, + typename CompletionCondition, typename WriteHandler> + inline void asio_handler_deallocate(void* pointer, std::size_t size, + write_op<AsyncWriteStream, ConstBufferSequence, + CompletionCondition, WriteHandler>* this_handler) + { + asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); + } + + template <typename AsyncWriteStream, typename ConstBufferSequence, + typename CompletionCondition, typename WriteHandler> + inline bool asio_handler_is_continuation( + write_op<AsyncWriteStream, ConstBufferSequence, + CompletionCondition, WriteHandler>* this_handler) + { + return this_handler->start_ == 0 ? true + : asio_handler_cont_helpers::is_continuation( + this_handler->handler_); + } + + template <typename Function, typename AsyncWriteStream, + typename ConstBufferSequence, typename CompletionCondition, + typename WriteHandler> + inline void asio_handler_invoke(Function& function, + write_op<AsyncWriteStream, ConstBufferSequence, + CompletionCondition, WriteHandler>* this_handler) + { + asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } + + template <typename Function, typename AsyncWriteStream, + typename ConstBufferSequence, typename CompletionCondition, + typename WriteHandler> + inline void asio_handler_invoke(const Function& function, + write_op<AsyncWriteStream, ConstBufferSequence, + CompletionCondition, WriteHandler>* this_handler) + { + asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } +} // namespace detail + +template <typename AsyncWriteStream, typename ConstBufferSequence, + typename CompletionCondition, typename WriteHandler> +inline ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (asio::error_code, std::size_t)) +async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, + CompletionCondition completion_condition, + ASIO_MOVE_ARG(WriteHandler) handler) +{ + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a WriteHandler. + ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + detail::async_result_init< + WriteHandler, void (asio::error_code, std::size_t)> init( + ASIO_MOVE_CAST(WriteHandler)(handler)); + + detail::write_op<AsyncWriteStream, ConstBufferSequence, + CompletionCondition, ASIO_HANDLER_TYPE( + WriteHandler, void (asio::error_code, std::size_t))>( + s, buffers, completion_condition, init.handler)( + asio::error_code(), 0, 1); + + return init.result.get(); +} + +template <typename AsyncWriteStream, typename ConstBufferSequence, + typename WriteHandler> +inline ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (asio::error_code, std::size_t)) +async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, + ASIO_MOVE_ARG(WriteHandler) handler) +{ + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a WriteHandler. + ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + detail::async_result_init< + WriteHandler, void (asio::error_code, std::size_t)> init( + ASIO_MOVE_CAST(WriteHandler)(handler)); + + detail::write_op<AsyncWriteStream, ConstBufferSequence, + detail::transfer_all_t, ASIO_HANDLER_TYPE( + WriteHandler, void (asio::error_code, std::size_t))>( + s, buffers, transfer_all(), init.handler)( + asio::error_code(), 0, 1); + + return init.result.get(); +} + + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IMPL_WRITE_HPP diff --git a/asio-1.10.6/include/asio/io_service.hpp b/asio-1.10.6/include/asio/io_service.hpp new file mode 100644 index 0000000..8439d9a --- /dev/null +++ b/asio-1.10.6/include/asio/io_service.hpp @@ -0,0 +1,747 @@ +// +// io_service.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IO_SERVICE_HPP +#define ASIO_IO_SERVICE_HPP + + +#include "asio/detail/config.hpp" +#include <cstddef> +#include <stdexcept> +#include <typeinfo> +#include "asio/async_result.hpp" +#include "asio/detail/noncopyable.hpp" +#include "asio/detail/wrapped_handler.hpp" +#include "asio/error_code.hpp" + +#if defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) || defined(__osf__) +# include "asio/detail/signal_init.hpp" +#endif + +#include "asio/detail/push_options.hpp" + +namespace asio { + +class io_service; +template <typename Service> Service& use_service(io_service& ios); +template <typename Service> void add_service(io_service& ios, Service* svc); +template <typename Service> bool has_service(io_service& ios); + +namespace detail { + typedef class task_io_service io_service_impl; + class service_registry; +} // namespace detail + +/// Provides core I/O functionality. +/** + * The io_service class provides the core I/O functionality for users of the + * asynchronous I/O objects, including: + * + * @li asio::ip::tcp::socket + * @li asio::ip::tcp::acceptor + * @li asio::ip::udp::socket + * @li asio::deadline_timer. + * + * The io_service class also includes facilities intended for developers of + * custom asynchronous services. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Safe, with the specific exceptions of the reset() and + * notify_fork() functions. Calling reset() while there are unfinished run(), + * run_one(), poll() or poll_one() calls results in undefined behaviour. The + * notify_fork() function should not be called while any io_service function, + * or any function on an I/O object that is associated with the io_service, is + * being called in another thread. + * + * @par Concepts: + * Dispatcher. + * + * @par Synchronous and asynchronous operations + * + * Synchronous operations on I/O objects implicitly run the io_service object + * for an individual operation. The io_service functions run(), run_one(), + * poll() or poll_one() must be called for the io_service to perform + * asynchronous operations on behalf of a C++ program. Notification that an + * asynchronous operation has completed is delivered by invocation of the + * associated handler. Handlers are invoked only by a thread that is currently + * calling any overload of run(), run_one(), poll() or poll_one() for the + * io_service. + * + * @par Effect of exceptions thrown from handlers + * + * If an exception is thrown from a handler, the exception is allowed to + * propagate through the throwing thread's invocation of run(), run_one(), + * poll() or poll_one(). No other threads that are calling any of these + * functions are affected. It is then the responsibility of the application to + * catch the exception. + * + * After the exception has been caught, the run(), run_one(), poll() or + * poll_one() call may be restarted @em without the need for an intervening + * call to reset(). This allows the thread to rejoin the io_service object's + * thread pool without impacting any other threads in the pool. + * + * For example: + * + * @code + * asio::io_service io_service; + * ... + * for (;;) + * { + * try + * { + * io_service.run(); + * break; // run() exited normally + * } + * catch (my_exception& e) + * { + * // Deal with exception as appropriate. + * } + * } + * @endcode + * + * @par Stopping the io_service from running out of work + * + * Some applications may need to prevent an io_service object's run() call from + * returning when there is no more work to do. For example, the io_service may + * be being run in a background thread that is launched prior to the + * application's asynchronous operations. The run() call may be kept running by + * creating an object of type asio::io_service::work: + * + * @code asio::io_service io_service; + * asio::io_service::work work(io_service); + * ... @endcode + * + * To effect a shutdown, the application will then need to call the io_service + * object's stop() member function. This will cause the io_service run() call + * to return as soon as possible, abandoning unfinished operations and without + * permitting ready handlers to be dispatched. + * + * Alternatively, if the application requires that all operations and handlers + * be allowed to finish normally, the work object may be explicitly destroyed. + * + * @code asio::io_service io_service; + * auto_ptr<asio::io_service::work> work( + * new asio::io_service::work(io_service)); + * ... + * work.reset(); // Allow run() to exit. @endcode + * + * @par The io_service class and I/O services + * + * Class io_service implements an extensible, type-safe, polymorphic set of I/O + * services, indexed by service type. An object of class io_service must be + * initialised before I/O objects such as sockets, resolvers and timers can be + * used. These I/O objects are distinguished by having constructors that accept + * an @c io_service& parameter. + * + * I/O services exist to manage the logical interface to the operating system on + * behalf of the I/O objects. In particular, there are resources that are shared + * across a class of I/O objects. For example, timers may be implemented in + * terms of a single timer queue. The I/O services manage these shared + * resources. + * + * Access to the services of an io_service is via three function templates, + * use_service(), add_service() and has_service(). + * + * In a call to @c use_service<Service>(), the type argument chooses a service, + * making available all members of the named type. If @c Service is not present + * in an io_service, an object of type @c Service is created and added to the + * io_service. A C++ program can check if an io_service implements a + * particular service with the function template @c has_service<Service>(). + * + * Service objects may be explicitly added to an io_service using the function + * template @c add_service<Service>(). If the @c Service is already present, the + * service_already_exists exception is thrown. If the owner of the service is + * not the same object as the io_service parameter, the invalid_service_owner + * exception is thrown. + * + * Once a service reference is obtained from an io_service object by calling + * use_service(), that reference remains usable as long as the owning io_service + * object exists. + * + * All I/O service implementations have io_service::service as a public base + * class. Custom I/O services may be implemented by deriving from this class and + * then added to an io_service using the facilities described above. + */ +class io_service + : private noncopyable +{ +private: + typedef detail::io_service_impl impl_type; + +public: + class work; + friend class work; + + class id; + + class service; + + class strand; + + /// Constructor. + ASIO_DECL io_service(); + + /// Constructor. + /** + * Construct with a hint about the required level of concurrency. + * + * @param concurrency_hint A suggestion to the implementation on how many + * threads it should allow to run simultaneously. + */ + ASIO_DECL explicit io_service(std::size_t concurrency_hint); + + /// Destructor. + /** + * On destruction, the io_service performs the following sequence of + * operations: + * + * @li For each service object @c svc in the io_service set, in reverse order + * of the beginning of service object lifetime, performs + * @c svc->shutdown_service(). + * + * @li Uninvoked handler objects that were scheduled for deferred invocation + * on the io_service, or any associated strand, are destroyed. + * + * @li For each service object @c svc in the io_service set, in reverse order + * of the beginning of service object lifetime, performs + * <tt>delete static_cast<io_service::service*>(svc)</tt>. + * + * @note The destruction sequence described above permits programs to + * simplify their resource management by using @c shared_ptr<>. Where an + * object's lifetime is tied to the lifetime of a connection (or some other + * sequence of asynchronous operations), a @c shared_ptr to the object would + * be bound into the handlers for all asynchronous operations associated with + * it. This works as follows: + * + * @li When a single connection ends, all associated asynchronous operations + * complete. The corresponding handler objects are destroyed, and all + * @c shared_ptr references to the objects are destroyed. + * + * @li To shut down the whole program, the io_service function stop() is + * called to terminate any run() calls as soon as possible. The io_service + * destructor defined above destroys all handlers, causing all @c shared_ptr + * references to all connection objects to be destroyed. + */ + ASIO_DECL ~io_service(); + + /// Run the io_service object's event processing loop. + /** + * The run() function blocks until all work has finished and there are no + * more handlers to be dispatched, or until the io_service has been stopped. + * + * Multiple threads may call the run() function to set up a pool of threads + * from which the io_service may execute handlers. All threads that are + * waiting in the pool are equivalent and the io_service may choose any one + * of them to invoke a handler. + * + * A normal exit from the run() function implies that the io_service object + * is stopped (the stopped() function returns @c true). Subsequent calls to + * run(), run_one(), poll() or poll_one() will return immediately unless there + * is a prior call to reset(). + * + * @return The number of handlers that were executed. + * + * @throws asio::system_error Thrown on failure. + * + * @note The run() function must not be called from a thread that is currently + * calling one of run(), run_one(), poll() or poll_one() on the same + * io_service object. + * + * The poll() function may also be used to dispatch ready handlers, but + * without blocking. + */ + ASIO_DECL std::size_t run(); + + /// Run the io_service object's event processing loop. + /** + * The run() function blocks until all work has finished and there are no + * more handlers to be dispatched, or until the io_service has been stopped. + * + * Multiple threads may call the run() function to set up a pool of threads + * from which the io_service may execute handlers. All threads that are + * waiting in the pool are equivalent and the io_service may choose any one + * of them to invoke a handler. + * + * A normal exit from the run() function implies that the io_service object + * is stopped (the stopped() function returns @c true). Subsequent calls to + * run(), run_one(), poll() or poll_one() will return immediately unless there + * is a prior call to reset(). + * + * @param ec Set to indicate what error occurred, if any. + * + * @return The number of handlers that were executed. + * + * @note The run() function must not be called from a thread that is currently + * calling one of run(), run_one(), poll() or poll_one() on the same + * io_service object. + * + * The poll() function may also be used to dispatch ready handlers, but + * without blocking. + */ + ASIO_DECL std::size_t run(asio::error_code& ec); + + /// Run the io_service object's event processing loop to execute at most one + /// handler. + /** + * The run_one() function blocks until one handler has been dispatched, or + * until the io_service has been stopped. + * + * @return The number of handlers that were executed. A zero return value + * implies that the io_service object is stopped (the stopped() function + * returns @c true). Subsequent calls to run(), run_one(), poll() or + * poll_one() will return immediately unless there is a prior call to + * reset(). + * + * @throws asio::system_error Thrown on failure. + */ + ASIO_DECL std::size_t run_one(); + + /// Run the io_service object's event processing loop to execute at most one + /// handler. + /** + * The run_one() function blocks until one handler has been dispatched, or + * until the io_service has been stopped. + * + * @return The number of handlers that were executed. A zero return value + * implies that the io_service object is stopped (the stopped() function + * returns @c true). Subsequent calls to run(), run_one(), poll() or + * poll_one() will return immediately unless there is a prior call to + * reset(). + * + * @return The number of handlers that were executed. + */ + ASIO_DECL std::size_t run_one(asio::error_code& ec); + + /// Run the io_service object's event processing loop to execute ready + /// handlers. + /** + * The poll() function runs handlers that are ready to run, without blocking, + * until the io_service has been stopped or there are no more ready handlers. + * + * @return The number of handlers that were executed. + * + * @throws asio::system_error Thrown on failure. + */ + ASIO_DECL std::size_t poll(); + + /// Run the io_service object's event processing loop to execute ready + /// handlers. + /** + * The poll() function runs handlers that are ready to run, without blocking, + * until the io_service has been stopped or there are no more ready handlers. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return The number of handlers that were executed. + */ + ASIO_DECL std::size_t poll(asio::error_code& ec); + + /// Run the io_service object's event processing loop to execute one ready + /// handler. + /** + * The poll_one() function runs at most one handler that is ready to run, + * without blocking. + * + * @return The number of handlers that were executed. + * + * @throws asio::system_error Thrown on failure. + */ + ASIO_DECL std::size_t poll_one(); + + /// Run the io_service object's event processing loop to execute one ready + /// handler. + /** + * The poll_one() function runs at most one handler that is ready to run, + * without blocking. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return The number of handlers that were executed. + */ + ASIO_DECL std::size_t poll_one(asio::error_code& ec); + + /// Stop the io_service object's event processing loop. + /** + * This function does not block, but instead simply signals the io_service to + * stop. All invocations of its run() or run_one() member functions should + * return as soon as possible. Subsequent calls to run(), run_one(), poll() + * or poll_one() will return immediately until reset() is called. + */ + ASIO_DECL void stop(); + + /// Determine whether the io_service object has been stopped. + /** + * This function is used to determine whether an io_service object has been + * stopped, either through an explicit call to stop(), or due to running out + * of work. When an io_service object is stopped, calls to run(), run_one(), + * poll() or poll_one() will return immediately without invoking any + * handlers. + * + * @return @c true if the io_service object is stopped, otherwise @c false. + */ + ASIO_DECL bool stopped() const; + + /// Reset the io_service in preparation for a subsequent run() invocation. + /** + * This function must be called prior to any second or later set of + * invocations of the run(), run_one(), poll() or poll_one() functions when a + * previous invocation of these functions returned due to the io_service + * being stopped or running out of work. After a call to reset(), the + * io_service object's stopped() function will return @c false. + * + * This function must not be called while there are any unfinished calls to + * the run(), run_one(), poll() or poll_one() functions. + */ + ASIO_DECL void reset(); + + /// Request the io_service to invoke the given handler. + /** + * This function is used to ask the io_service to execute the given handler. + * + * The io_service guarantees that the handler will only be called in a thread + * in which the run(), run_one(), poll() or poll_one() member functions is + * currently being invoked. The handler may be executed inside this function + * if the guarantee can be met. + * + * @param handler The handler to be called. The io_service will make + * a copy of the handler object as required. The function signature of the + * handler must be: @code void handler(); @endcode + * + * @note This function throws an exception only if: + * + * @li the handler's @c asio_handler_allocate function; or + * + * @li the handler's copy constructor + * + * throws an exception. + */ + template <typename CompletionHandler> + ASIO_INITFN_RESULT_TYPE(CompletionHandler, void ()) + dispatch(ASIO_MOVE_ARG(CompletionHandler) handler); + + /// Request the io_service to invoke the given handler and return immediately. + /** + * This function is used to ask the io_service to execute the given handler, + * but without allowing the io_service to call the handler from inside this + * function. + * + * The io_service guarantees that the handler will only be called in a thread + * in which the run(), run_one(), poll() or poll_one() member functions is + * currently being invoked. + * + * @param handler The handler to be called. The io_service will make + * a copy of the handler object as required. The function signature of the + * handler must be: @code void handler(); @endcode + * + * @note This function throws an exception only if: + * + * @li the handler's @c asio_handler_allocate function; or + * + * @li the handler's copy constructor + * + * throws an exception. + */ + template <typename CompletionHandler> + ASIO_INITFN_RESULT_TYPE(CompletionHandler, void ()) + post(ASIO_MOVE_ARG(CompletionHandler) handler); + + /// Create a new handler that automatically dispatches the wrapped handler + /// on the io_service. + /** + * This function is used to create a new handler function object that, when + * invoked, will automatically pass the wrapped handler to the io_service + * object's dispatch function. + * + * @param handler The handler to be wrapped. The io_service will make a copy + * of the handler object as required. The function signature of the handler + * must be: @code void handler(A1 a1, ... An an); @endcode + * + * @return A function object that, when invoked, passes the wrapped handler to + * the io_service object's dispatch function. Given a function object with the + * signature: + * @code R f(A1 a1, ... An an); @endcode + * If this function object is passed to the wrap function like so: + * @code io_service.wrap(f); @endcode + * then the return value is a function object with the signature + * @code void g(A1 a1, ... An an); @endcode + * that, when invoked, executes code equivalent to: + * @code io_service.dispatch(boost::bind(f, a1, ... an)); @endcode + */ + template <typename Handler> + detail::wrapped_handler<io_service&, Handler> + wrap(Handler handler); + + /// Fork-related event notifications. + enum fork_event + { + /// Notify the io_service that the process is about to fork. + fork_prepare, + + /// Notify the io_service that the process has forked and is the parent. + fork_parent, + + /// Notify the io_service that the process has forked and is the child. + fork_child + }; + + /// Notify the io_service of a fork-related event. + /** + * This function is used to inform the io_service that the process is about + * to fork, or has just forked. This allows the io_service, and the services + * it contains, to perform any necessary housekeeping to ensure correct + * operation following a fork. + * + * This function must not be called while any other io_service function, or + * any function on an I/O object associated with the io_service, is being + * called in another thread. It is, however, safe to call this function from + * within a completion handler, provided no other thread is accessing the + * io_service. + * + * @param event A fork-related event. + * + * @throws asio::system_error Thrown on failure. If the notification + * fails the io_service object should no longer be used and should be + * destroyed. + * + * @par Example + * The following code illustrates how to incorporate the notify_fork() + * function: + * @code my_io_service.notify_fork(asio::io_service::fork_prepare); + * if (fork() == 0) + * { + * // This is the child process. + * my_io_service.notify_fork(asio::io_service::fork_child); + * } + * else + * { + * // This is the parent process. + * my_io_service.notify_fork(asio::io_service::fork_parent); + * } @endcode + * + * @note For each service object @c svc in the io_service set, performs + * <tt>svc->fork_service();</tt>. When processing the fork_prepare event, + * services are visited in reverse order of the beginning of service object + * lifetime. Otherwise, services are visited in order of the beginning of + * service object lifetime. + */ + ASIO_DECL void notify_fork(asio::io_service::fork_event event); + + /// Obtain the service object corresponding to the given type. + /** + * This function is used to locate a service object that corresponds to + * the given service type. If there is no existing implementation of the + * service, then the io_service will create a new instance of the service. + * + * @param ios The io_service object that owns the service. + * + * @return The service interface implementing the specified service type. + * Ownership of the service interface is not transferred to the caller. + */ + template <typename Service> + friend Service& use_service(io_service& ios); + + /// Add a service object to the io_service. + /** + * This function is used to add a service to the io_service. + * + * @param ios The io_service object that owns the service. + * + * @param svc The service object. On success, ownership of the service object + * is transferred to the io_service. When the io_service object is destroyed, + * it will destroy the service object by performing: + * @code delete static_cast<io_service::service*>(svc) @endcode + * + * @throws asio::service_already_exists Thrown if a service of the + * given type is already present in the io_service. + * + * @throws asio::invalid_service_owner Thrown if the service's owning + * io_service is not the io_service object specified by the ios parameter. + */ + template <typename Service> + friend void add_service(io_service& ios, Service* svc); + + /// Determine if an io_service contains a specified service type. + /** + * This function is used to determine whether the io_service contains a + * service object corresponding to the given service type. + * + * @param ios The io_service object that owns the service. + * + * @return A boolean indicating whether the io_service contains the service. + */ + template <typename Service> + friend bool has_service(io_service& ios); + +private: +#if defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) || defined(__osf__) + detail::signal_init<> init_; +#endif + + // The service registry. + asio::detail::service_registry* service_registry_; + + // The implementation. + impl_type& impl_; +}; + +/// Class to inform the io_service when it has work to do. +/** + * The work class is used to inform the io_service when work starts and + * finishes. This ensures that the io_service object's run() function will not + * exit while work is underway, and that it does exit when there is no + * unfinished work remaining. + * + * The work class is copy-constructible so that it may be used as a data member + * in a handler class. It is not assignable. + */ +class io_service::work +{ +public: + /// Constructor notifies the io_service that work is starting. + /** + * The constructor is used to inform the io_service that some work has begun. + * This ensures that the io_service object's run() function will not exit + * while the work is underway. + */ + explicit work(asio::io_service& io_service); + + /// Copy constructor notifies the io_service that work is starting. + /** + * The constructor is used to inform the io_service that some work has begun. + * This ensures that the io_service object's run() function will not exit + * while the work is underway. + */ + work(const work& other); + + /// Destructor notifies the io_service that the work is complete. + /** + * The destructor is used to inform the io_service that some work has + * finished. Once the count of unfinished work reaches zero, the io_service + * object's run() function is permitted to exit. + */ + ~work(); + + /// Get the io_service associated with the work. + asio::io_service& get_io_service(); + +private: + // Prevent assignment. + void operator=(const work& other); + + // The io_service implementation. + detail::io_service_impl& io_service_impl_; +}; + +/// Class used to uniquely identify a service. +class io_service::id + : private noncopyable +{ +public: + /// Constructor. + id() {} +}; + +/// Base class for all io_service services. +class io_service::service + : private noncopyable +{ +public: + /// Get the io_service object that owns the service. + asio::io_service& get_io_service(); + +protected: + /// Constructor. + /** + * @param owner The io_service object that owns the service. + */ + ASIO_DECL service(asio::io_service& owner); + + /// Destructor. + ASIO_DECL virtual ~service(); + +private: + /// Destroy all user-defined handler objects owned by the service. + virtual void shutdown_service() = 0; + + /// Handle notification of a fork-related event to perform any necessary + /// housekeeping. + /** + * This function is not a pure virtual so that services only have to + * implement it if necessary. The default implementation does nothing. + */ + ASIO_DECL virtual void fork_service( + asio::io_service::fork_event event); + + friend class asio::detail::service_registry; + struct key + { + key() : type_info_(0), id_(0) {} + const std::type_info* type_info_; + const asio::io_service::id* id_; + } key_; + + asio::io_service& owner_; + service* next_; +}; + +/// Exception thrown when trying to add a duplicate service to an io_service. +class service_already_exists + : public std::logic_error +{ +public: + ASIO_DECL service_already_exists(); +}; + +/// Exception thrown when trying to add a service object to an io_service where +/// the service has a different owner. +class invalid_service_owner + : public std::logic_error +{ +public: + ASIO_DECL invalid_service_owner(); +}; + +namespace detail { + +// Special derived service id type to keep classes header-file only. +template <typename Type> +class service_id + : public asio::io_service::id +{ +}; + +// Special service base class to keep classes header-file only. +template <typename Type> +class service_base + : public asio::io_service::service +{ +public: + static asio::detail::service_id<Type> id; + + // Constructor. + service_base(asio::io_service& io_service) + : asio::io_service::service(io_service) + { + } +}; + +template <typename Type> +asio::detail::service_id<Type> service_base<Type>::id; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#include "asio/impl/io_service.hpp" +# include "asio/impl/io_service.ipp" + +#endif // ASIO_IO_SERVICE_HPP diff --git a/asio-1.10.6/include/asio/ip/address.hpp b/asio-1.10.6/include/asio/ip/address.hpp new file mode 100644 index 0000000..bae5871 --- /dev/null +++ b/asio-1.10.6/include/asio/ip/address.hpp @@ -0,0 +1,169 @@ +// +// ip/address.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_ADDRESS_HPP +#define ASIO_IP_ADDRESS_HPP + + +#include "asio/detail/config.hpp" +#include <string> +#include "asio/error_code.hpp" +#include "asio/ip/address_v4.hpp" +#include "asio/ip/address_v6.hpp" + + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { + +/// Implements version-independent IP addresses. +/** + * The asio::ip::address class provides the ability to use either IP + * version 4 or version 6 addresses. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +class address +{ +public: + /// Default constructor. + ASIO_DECL address(); + + /// Construct an address from an IPv4 address. + ASIO_DECL address(const asio::ip::address_v4& ipv4_address); + + /// Construct an address from an IPv6 address. + ASIO_DECL address(const asio::ip::address_v6& ipv6_address); + + /// Copy constructor. + ASIO_DECL address(const address& other); + + /// Move constructor. + ASIO_DECL address(address&& other); + + /// Assign from another address. + ASIO_DECL address& operator=(const address& other); + + /// Move-assign from another address. + ASIO_DECL address& operator=(address&& other); + + /// Assign from an IPv4 address. + ASIO_DECL address& operator=( + const asio::ip::address_v4& ipv4_address); + + /// Assign from an IPv6 address. + ASIO_DECL address& operator=( + const asio::ip::address_v6& ipv6_address); + + /// Get whether the address is an IP version 4 address. + bool is_v4() const + { + return type_ == ipv4; + } + + /// Get whether the address is an IP version 6 address. + bool is_v6() const + { + return type_ == ipv6; + } + + /// Get the address as an IP version 4 address. + ASIO_DECL asio::ip::address_v4 to_v4() const; + + /// Get the address as an IP version 6 address. + ASIO_DECL asio::ip::address_v6 to_v6() const; + + /// Get the address as a string in dotted decimal format. + ASIO_DECL std::string to_string() const; + + /// Get the address as a string in dotted decimal format. + ASIO_DECL std::string to_string(asio::error_code& ec) const; + + /// Create an address from an IPv4 address string in dotted decimal form, + /// or from an IPv6 address in hexadecimal notation. + ASIO_DECL static address from_string(const char* str); + + /// Create an address from an IPv4 address string in dotted decimal form, + /// or from an IPv6 address in hexadecimal notation. + ASIO_DECL static address from_string( + const char* str, asio::error_code& ec); + + /// Create an address from an IPv4 address string in dotted decimal form, + /// or from an IPv6 address in hexadecimal notation. + ASIO_DECL static address from_string(const std::string& str); + + /// Create an address from an IPv4 address string in dotted decimal form, + /// or from an IPv6 address in hexadecimal notation. + ASIO_DECL static address from_string( + const std::string& str, asio::error_code& ec); + + /// Determine whether the address is a loopback address. + ASIO_DECL bool is_loopback() const; + + /// Determine whether the address is unspecified. + ASIO_DECL bool is_unspecified() const; + + /// Determine whether the address is a multicast address. + ASIO_DECL bool is_multicast() const; + + /// Compare two addresses for equality. + ASIO_DECL friend bool operator==(const address& a1, const address& a2); + + /// Compare two addresses for inequality. + friend bool operator!=(const address& a1, const address& a2) + { + return !(a1 == a2); + } + + /// Compare addresses for ordering. + ASIO_DECL friend bool operator<(const address& a1, const address& a2); + + /// Compare addresses for ordering. + friend bool operator>(const address& a1, const address& a2) + { + return a2 < a1; + } + + /// Compare addresses for ordering. + friend bool operator<=(const address& a1, const address& a2) + { + return !(a2 < a1); + } + + /// Compare addresses for ordering. + friend bool operator>=(const address& a1, const address& a2) + { + return !(a1 < a2); + } + +private: + // The type of the address. + enum { ipv4, ipv6 } type_; + + // The underlying IPv4 address. + asio::ip::address_v4 ipv4_address_; + + // The underlying IPv6 address. + asio::ip::address_v6 ipv6_address_; +}; + + +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#include "asio/ip/impl/address.hpp" +# include "asio/ip/impl/address.ipp" + +#endif // ASIO_IP_ADDRESS_HPP diff --git a/asio-1.10.6/include/asio/ip/address_v4.hpp b/asio-1.10.6/include/asio/ip/address_v4.hpp new file mode 100644 index 0000000..4b6d5e8 --- /dev/null +++ b/asio-1.10.6/include/asio/ip/address_v4.hpp @@ -0,0 +1,206 @@ +// +// ip/address_v4.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_ADDRESS_V4_HPP +#define ASIO_IP_ADDRESS_V4_HPP + + +#include "asio/detail/config.hpp" +#include <string> +#include "asio/detail/array.hpp" +#include "asio/detail/socket_types.hpp" +#include "asio/detail/winsock_init.hpp" +#include "asio/error_code.hpp" + + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { + +/// Implements IP version 4 style addresses. +/** + * The asio::ip::address_v4 class provides the ability to use and + * manipulate IP version 4 addresses. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +class address_v4 +{ +public: + /// The type used to represent an address as an array of bytes. + /** + * @note This type is defined in terms of the C++0x template @c std::array + * when it is available. Otherwise, it uses @c boost:array. + */ + typedef asio::detail::array<unsigned char, 4> bytes_type; + + /// Default constructor. + address_v4() + { + addr_.s_addr = 0; + } + + /// Construct an address from raw bytes. + ASIO_DECL explicit address_v4(const bytes_type& bytes); + + /// Construct an address from a unsigned long in host byte order. + ASIO_DECL explicit address_v4(unsigned long addr); + + /// Copy constructor. + address_v4(const address_v4& other) + : addr_(other.addr_) + { + } + + /// Move constructor. + address_v4(address_v4&& other) + : addr_(other.addr_) + { + } + + /// Assign from another address. + address_v4& operator=(const address_v4& other) + { + addr_ = other.addr_; + return *this; + } + + /// Move-assign from another address. + address_v4& operator=(address_v4&& other) + { + addr_ = other.addr_; + return *this; + } + + /// Get the address in bytes, in network byte order. + ASIO_DECL bytes_type to_bytes() const; + + /// Get the address as an unsigned long in host byte order + ASIO_DECL unsigned long to_ulong() const; + + /// Get the address as a string in dotted decimal format. + ASIO_DECL std::string to_string() const; + + /// Get the address as a string in dotted decimal format. + ASIO_DECL std::string to_string(asio::error_code& ec) const; + + /// Create an address from an IP address string in dotted decimal form. + ASIO_DECL static address_v4 from_string(const char* str); + + /// Create an address from an IP address string in dotted decimal form. + ASIO_DECL static address_v4 from_string( + const char* str, asio::error_code& ec); + + /// Create an address from an IP address string in dotted decimal form. + ASIO_DECL static address_v4 from_string(const std::string& str); + + /// Create an address from an IP address string in dotted decimal form. + ASIO_DECL static address_v4 from_string( + const std::string& str, asio::error_code& ec); + + /// Determine whether the address is a loopback address. + ASIO_DECL bool is_loopback() const; + + /// Determine whether the address is unspecified. + ASIO_DECL bool is_unspecified() const; + + /// Determine whether the address is a class A address. + ASIO_DECL bool is_class_a() const; + + /// Determine whether the address is a class B address. + ASIO_DECL bool is_class_b() const; + + /// Determine whether the address is a class C address. + ASIO_DECL bool is_class_c() const; + + /// Determine whether the address is a multicast address. + ASIO_DECL bool is_multicast() const; + + /// Compare two addresses for equality. + friend bool operator==(const address_v4& a1, const address_v4& a2) + { + return a1.addr_.s_addr == a2.addr_.s_addr; + } + + /// Compare two addresses for inequality. + friend bool operator!=(const address_v4& a1, const address_v4& a2) + { + return a1.addr_.s_addr != a2.addr_.s_addr; + } + + /// Compare addresses for ordering. + friend bool operator<(const address_v4& a1, const address_v4& a2) + { + return a1.to_ulong() < a2.to_ulong(); + } + + /// Compare addresses for ordering. + friend bool operator>(const address_v4& a1, const address_v4& a2) + { + return a1.to_ulong() > a2.to_ulong(); + } + + /// Compare addresses for ordering. + friend bool operator<=(const address_v4& a1, const address_v4& a2) + { + return a1.to_ulong() <= a2.to_ulong(); + } + + /// Compare addresses for ordering. + friend bool operator>=(const address_v4& a1, const address_v4& a2) + { + return a1.to_ulong() >= a2.to_ulong(); + } + + /// Obtain an address object that represents any address. + static address_v4 any() + { + return address_v4(); + } + + /// Obtain an address object that represents the loopback address. + static address_v4 loopback() + { + return address_v4(0x7F000001); + } + + /// Obtain an address object that represents the broadcast address. + static address_v4 broadcast() + { + return address_v4(0xFFFFFFFF); + } + + /// Obtain an address object that represents the broadcast address that + /// corresponds to the specified address and netmask. + ASIO_DECL static address_v4 broadcast( + const address_v4& addr, const address_v4& mask); + + /// Obtain the netmask that corresponds to the address, based on its address + /// class. + ASIO_DECL static address_v4 netmask(const address_v4& addr); + +private: + // The underlying IPv4 address. + asio::detail::in4_addr_type addr_; +}; + + +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#include "asio/ip/impl/address_v4.hpp" +# include "asio/ip/impl/address_v4.ipp" + +#endif // ASIO_IP_ADDRESS_V4_HPP diff --git a/asio-1.10.6/include/asio/ip/address_v6.hpp b/asio-1.10.6/include/asio/ip/address_v6.hpp new file mode 100644 index 0000000..b8602c3 --- /dev/null +++ b/asio-1.10.6/include/asio/ip/address_v6.hpp @@ -0,0 +1,211 @@ +// +// ip/address_v6.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_ADDRESS_V6_HPP +#define ASIO_IP_ADDRESS_V6_HPP + + +#include "asio/detail/config.hpp" +#include <string> +#include "asio/detail/array.hpp" +#include "asio/detail/socket_types.hpp" +#include "asio/detail/winsock_init.hpp" +#include "asio/error_code.hpp" +#include "asio/ip/address_v4.hpp" + + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { + +/// Implements IP version 6 style addresses. +/** + * The asio::ip::address_v6 class provides the ability to use and + * manipulate IP version 6 addresses. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +class address_v6 +{ +public: + /// The type used to represent an address as an array of bytes. + /** + * @note This type is defined in terms of the C++0x template @c std::array + * when it is available. Otherwise, it uses @c boost:array. + */ + typedef asio::detail::array<unsigned char, 16> bytes_type; + + /// Default constructor. + ASIO_DECL address_v6(); + + /// Construct an address from raw bytes and scope ID. + ASIO_DECL explicit address_v6(const bytes_type& bytes, + unsigned long scope_id = 0); + + /// Copy constructor. + ASIO_DECL address_v6(const address_v6& other); + + /// Move constructor. + ASIO_DECL address_v6(address_v6&& other); + + /// Assign from another address. + ASIO_DECL address_v6& operator=(const address_v6& other); + + /// Move-assign from another address. + ASIO_DECL address_v6& operator=(address_v6&& other); + + /// The scope ID of the address. + /** + * Returns the scope ID associated with the IPv6 address. + */ + unsigned long scope_id() const + { + return scope_id_; + } + + /// The scope ID of the address. + /** + * Modifies the scope ID associated with the IPv6 address. + */ + void scope_id(unsigned long id) + { + scope_id_ = id; + } + + /// Get the address in bytes, in network byte order. + ASIO_DECL bytes_type to_bytes() const; + + /// Get the address as a string. + ASIO_DECL std::string to_string() const; + + /// Get the address as a string. + ASIO_DECL std::string to_string(asio::error_code& ec) const; + + /// Create an address from an IP address string. + ASIO_DECL static address_v6 from_string(const char* str); + + /// Create an address from an IP address string. + ASIO_DECL static address_v6 from_string( + const char* str, asio::error_code& ec); + + /// Create an address from an IP address string. + ASIO_DECL static address_v6 from_string(const std::string& str); + + /// Create an address from an IP address string. + ASIO_DECL static address_v6 from_string( + const std::string& str, asio::error_code& ec); + + /// Converts an IPv4-mapped or IPv4-compatible address to an IPv4 address. + ASIO_DECL address_v4 to_v4() const; + + /// Determine whether the address is a loopback address. + ASIO_DECL bool is_loopback() const; + + /// Determine whether the address is unspecified. + ASIO_DECL bool is_unspecified() const; + + /// Determine whether the address is link local. + ASIO_DECL bool is_link_local() const; + + /// Determine whether the address is site local. + ASIO_DECL bool is_site_local() const; + + /// Determine whether the address is a mapped IPv4 address. + ASIO_DECL bool is_v4_mapped() const; + + /// Determine whether the address is an IPv4-compatible address. + ASIO_DECL bool is_v4_compatible() const; + + /// Determine whether the address is a multicast address. + ASIO_DECL bool is_multicast() const; + + /// Determine whether the address is a global multicast address. + ASIO_DECL bool is_multicast_global() const; + + /// Determine whether the address is a link-local multicast address. + ASIO_DECL bool is_multicast_link_local() const; + + /// Determine whether the address is a node-local multicast address. + ASIO_DECL bool is_multicast_node_local() const; + + /// Determine whether the address is a org-local multicast address. + ASIO_DECL bool is_multicast_org_local() const; + + /// Determine whether the address is a site-local multicast address. + ASIO_DECL bool is_multicast_site_local() const; + + /// Compare two addresses for equality. + ASIO_DECL friend bool operator==( + const address_v6& a1, const address_v6& a2); + + /// Compare two addresses for inequality. + friend bool operator!=(const address_v6& a1, const address_v6& a2) + { + return !(a1 == a2); + } + + /// Compare addresses for ordering. + ASIO_DECL friend bool operator<( + const address_v6& a1, const address_v6& a2); + + /// Compare addresses for ordering. + friend bool operator>(const address_v6& a1, const address_v6& a2) + { + return a2 < a1; + } + + /// Compare addresses for ordering. + friend bool operator<=(const address_v6& a1, const address_v6& a2) + { + return !(a2 < a1); + } + + /// Compare addresses for ordering. + friend bool operator>=(const address_v6& a1, const address_v6& a2) + { + return !(a1 < a2); + } + + /// Obtain an address object that represents any address. + static address_v6 any() + { + return address_v6(); + } + + /// Obtain an address object that represents the loopback address. + ASIO_DECL static address_v6 loopback(); + + /// Create an IPv4-mapped IPv6 address. + ASIO_DECL static address_v6 v4_mapped(const address_v4& addr); + + /// Create an IPv4-compatible IPv6 address. + ASIO_DECL static address_v6 v4_compatible(const address_v4& addr); + +private: + // The underlying IPv6 address. + asio::detail::in6_addr_type addr_; + + // The scope ID associated with the address. + unsigned long scope_id_; +}; + + +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#include "asio/ip/impl/address_v6.hpp" +# include "asio/ip/impl/address_v6.ipp" + +#endif // ASIO_IP_ADDRESS_V6_HPP diff --git a/asio-1.10.6/include/asio/ip/basic_endpoint.hpp b/asio-1.10.6/include/asio/ip/basic_endpoint.hpp new file mode 100644 index 0000000..43bfa8f --- /dev/null +++ b/asio-1.10.6/include/asio/ip/basic_endpoint.hpp @@ -0,0 +1,229 @@ +// +// ip/basic_endpoint.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_BASIC_ENDPOINT_HPP +#define ASIO_IP_BASIC_ENDPOINT_HPP + + +#include "asio/detail/config.hpp" +#include "asio/ip/address.hpp" +#include "asio/ip/detail/endpoint.hpp" + + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { + +/// Describes an endpoint for a version-independent IP socket. +/** + * The asio::ip::basic_endpoint class template describes an endpoint that + * may be associated with a particular socket. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Concepts: + * Endpoint. + */ +template <typename InternetProtocol> +class basic_endpoint +{ +public: + /// The protocol type associated with the endpoint. + typedef InternetProtocol protocol_type; + + /// The type of the endpoint structure. This type is dependent on the + /// underlying implementation of the socket layer. + typedef asio::detail::socket_addr_type data_type; + + /// Default constructor. + basic_endpoint() + : impl_() + { + } + + /// Construct an endpoint using a port number, specified in the host's byte + /// order. The IP address will be the any address (i.e. INADDR_ANY or + /// in6addr_any). This constructor would typically be used for accepting new + /// connections. + /** + * @par Examples + * To initialise an IPv4 TCP endpoint for port 1234, use: + * @code + * asio::ip::tcp::endpoint ep(asio::ip::tcp::v4(), 1234); + * @endcode + * + * To specify an IPv6 UDP endpoint for port 9876, use: + * @code + * asio::ip::udp::endpoint ep(asio::ip::udp::v6(), 9876); + * @endcode + */ + basic_endpoint(const InternetProtocol& internet_protocol, + unsigned short port_num) + : impl_(internet_protocol.family(), port_num) + { + } + + /// Construct an endpoint using a port number and an IP address. This + /// constructor may be used for accepting connections on a specific interface + /// or for making a connection to a remote endpoint. + basic_endpoint(const asio::ip::address& addr, unsigned short port_num) + : impl_(addr, port_num) + { + } + + /// Copy constructor. + basic_endpoint(const basic_endpoint& other) + : impl_(other.impl_) + { + } + + /// Move constructor. + basic_endpoint(basic_endpoint&& other) + : impl_(other.impl_) + { + } + + /// Assign from another endpoint. + basic_endpoint& operator=(const basic_endpoint& other) + { + impl_ = other.impl_; + return *this; + } + + /// Move-assign from another endpoint. + basic_endpoint& operator=(basic_endpoint&& other) + { + impl_ = other.impl_; + return *this; + } + + /// The protocol associated with the endpoint. + protocol_type protocol() const + { + if (impl_.is_v4()) + return InternetProtocol::v4(); + return InternetProtocol::v6(); + } + + /// Get the underlying endpoint in the native type. + data_type* data() + { + return impl_.data(); + } + + /// Get the underlying endpoint in the native type. + const data_type* data() const + { + return impl_.data(); + } + + /// Get the underlying size of the endpoint in the native type. + std::size_t size() const + { + return impl_.size(); + } + + /// Set the underlying size of the endpoint in the native type. + void resize(std::size_t new_size) + { + impl_.resize(new_size); + } + + /// Get the capacity of the endpoint in the native type. + std::size_t capacity() const + { + return impl_.capacity(); + } + + /// Get the port associated with the endpoint. The port number is always in + /// the host's byte order. + unsigned short port() const + { + return impl_.port(); + } + + /// Set the port associated with the endpoint. The port number is always in + /// the host's byte order. + void port(unsigned short port_num) + { + impl_.port(port_num); + } + + /// Get the IP address associated with the endpoint. + asio::ip::address address() const + { + return impl_.address(); + } + + /// Set the IP address associated with the endpoint. + void address(const asio::ip::address& addr) + { + impl_.address(addr); + } + + /// Compare two endpoints for equality. + friend bool operator==(const basic_endpoint<InternetProtocol>& e1, + const basic_endpoint<InternetProtocol>& e2) + { + return e1.impl_ == e2.impl_; + } + + /// Compare two endpoints for inequality. + friend bool operator!=(const basic_endpoint<InternetProtocol>& e1, + const basic_endpoint<InternetProtocol>& e2) + { + return !(e1 == e2); + } + + /// Compare endpoints for ordering. + friend bool operator<(const basic_endpoint<InternetProtocol>& e1, + const basic_endpoint<InternetProtocol>& e2) + { + return e1.impl_ < e2.impl_; + } + + /// Compare endpoints for ordering. + friend bool operator>(const basic_endpoint<InternetProtocol>& e1, + const basic_endpoint<InternetProtocol>& e2) + { + return e2.impl_ < e1.impl_; + } + + /// Compare endpoints for ordering. + friend bool operator<=(const basic_endpoint<InternetProtocol>& e1, + const basic_endpoint<InternetProtocol>& e2) + { + return !(e2 < e1); + } + + /// Compare endpoints for ordering. + friend bool operator>=(const basic_endpoint<InternetProtocol>& e1, + const basic_endpoint<InternetProtocol>& e2) + { + return !(e1 < e2); + } + +private: + // The underlying IP endpoint. + asio::ip::detail::endpoint impl_; +}; + + +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#include "asio/ip/impl/basic_endpoint.hpp" + +#endif // ASIO_IP_BASIC_ENDPOINT_HPP diff --git a/asio-1.10.6/include/asio/ip/basic_resolver.hpp b/asio-1.10.6/include/asio/ip/basic_resolver.hpp new file mode 100644 index 0000000..8097ae1 --- /dev/null +++ b/asio-1.10.6/include/asio/ip/basic_resolver.hpp @@ -0,0 +1,265 @@ +// +// ip/basic_resolver.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_BASIC_RESOLVER_HPP +#define ASIO_IP_BASIC_RESOLVER_HPP + + +#include "asio/detail/config.hpp" +#include "asio/basic_io_object.hpp" +#include "asio/detail/handler_type_requirements.hpp" +#include "asio/detail/throw_error.hpp" +#include "asio/error.hpp" +#include "asio/ip/basic_resolver_iterator.hpp" +#include "asio/ip/basic_resolver_query.hpp" +#include "asio/ip/resolver_service.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { + +/// Provides endpoint resolution functionality. +/** + * The basic_resolver class template provides the ability to resolve a query + * to a list of endpoints. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template <typename InternetProtocol, + typename ResolverService = resolver_service<InternetProtocol> > +class basic_resolver + : public basic_io_object<ResolverService> +{ +public: + /// The protocol type. + typedef InternetProtocol protocol_type; + + /// The endpoint type. + typedef typename InternetProtocol::endpoint endpoint_type; + + /// The query type. + typedef basic_resolver_query<InternetProtocol> query; + + /// The iterator type. + typedef basic_resolver_iterator<InternetProtocol> iterator; + + /// Constructor. + /** + * This constructor creates a basic_resolver. + * + * @param io_service The io_service object that the resolver will use to + * dispatch handlers for any asynchronous operations performed on the timer. + */ + explicit basic_resolver(asio::io_service& io_service) + : basic_io_object<ResolverService>(io_service) + { + } + + /// Cancel any asynchronous operations that are waiting on the resolver. + /** + * This function forces the completion of any pending asynchronous + * operations on the host resolver. The handler for each cancelled operation + * will be invoked with the asio::error::operation_aborted error code. + */ + void cancel() + { + return this->service.cancel(this->implementation); + } + + /// Perform forward resolution of a query to a list of entries. + /** + * This function is used to resolve a query into a list of endpoint entries. + * + * @param q A query object that determines what endpoints will be returned. + * + * @returns A forward-only iterator that can be used to traverse the list + * of endpoint entries. + * + * @throws asio::system_error Thrown on failure. + * + * @note A default constructed iterator represents the end of the list. + * + * A successful call to this function is guaranteed to return at least one + * entry. + */ + iterator resolve(const query& q) + { + asio::error_code ec; + iterator i = this->service.resolve(this->implementation, q, ec); + asio::detail::throw_error(ec, "resolve"); + return i; + } + + /// Perform forward resolution of a query to a list of entries. + /** + * This function is used to resolve a query into a list of endpoint entries. + * + * @param q A query object that determines what endpoints will be returned. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns A forward-only iterator that can be used to traverse the list + * of endpoint entries. Returns a default constructed iterator if an error + * occurs. + * + * @note A default constructed iterator represents the end of the list. + * + * A successful call to this function is guaranteed to return at least one + * entry. + */ + iterator resolve(const query& q, asio::error_code& ec) + { + return this->service.resolve(this->implementation, q, ec); + } + + /// Asynchronously perform forward resolution of a query to a list of entries. + /** + * This function is used to asynchronously resolve a query into a list of + * endpoint entries. + * + * @param q A query object that determines what endpoints will be returned. + * + * @param handler The handler to be called when the resolve operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * resolver::iterator iterator // Forward-only iterator that can + * // be used to traverse the list + * // of endpoint entries. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note A default constructed iterator represents the end of the list. + * + * A successful resolve operation is guaranteed to pass at least one entry to + * the handler. + */ + template <typename ResolveHandler> + ASIO_INITFN_RESULT_TYPE(ResolveHandler, + void (asio::error_code, iterator)) + async_resolve(const query& q, + ASIO_MOVE_ARG(ResolveHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ResolveHandler. + ASIO_RESOLVE_HANDLER_CHECK( + ResolveHandler, handler, iterator) type_check; + + return this->service.async_resolve(this->implementation, q, + ASIO_MOVE_CAST(ResolveHandler)(handler)); + } + + /// Perform reverse resolution of an endpoint to a list of entries. + /** + * This function is used to resolve an endpoint into a list of endpoint + * entries. + * + * @param e An endpoint object that determines what endpoints will be + * returned. + * + * @returns A forward-only iterator that can be used to traverse the list + * of endpoint entries. + * + * @throws asio::system_error Thrown on failure. + * + * @note A default constructed iterator represents the end of the list. + * + * A successful call to this function is guaranteed to return at least one + * entry. + */ + iterator resolve(const endpoint_type& e) + { + asio::error_code ec; + iterator i = this->service.resolve(this->implementation, e, ec); + asio::detail::throw_error(ec, "resolve"); + return i; + } + + /// Perform reverse resolution of an endpoint to a list of entries. + /** + * This function is used to resolve an endpoint into a list of endpoint + * entries. + * + * @param e An endpoint object that determines what endpoints will be + * returned. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns A forward-only iterator that can be used to traverse the list + * of endpoint entries. Returns a default constructed iterator if an error + * occurs. + * + * @note A default constructed iterator represents the end of the list. + * + * A successful call to this function is guaranteed to return at least one + * entry. + */ + iterator resolve(const endpoint_type& e, asio::error_code& ec) + { + return this->service.resolve(this->implementation, e, ec); + } + + /// Asynchronously perform reverse resolution of an endpoint to a list of + /// entries. + /** + * This function is used to asynchronously resolve an endpoint into a list of + * endpoint entries. + * + * @param e An endpoint object that determines what endpoints will be + * returned. + * + * @param handler The handler to be called when the resolve operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * resolver::iterator iterator // Forward-only iterator that can + * // be used to traverse the list + * // of endpoint entries. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note A default constructed iterator represents the end of the list. + * + * A successful resolve operation is guaranteed to pass at least one entry to + * the handler. + */ + template <typename ResolveHandler> + ASIO_INITFN_RESULT_TYPE(ResolveHandler, + void (asio::error_code, iterator)) + async_resolve(const endpoint_type& e, + ASIO_MOVE_ARG(ResolveHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ResolveHandler. + ASIO_RESOLVE_HANDLER_CHECK( + ResolveHandler, handler, iterator) type_check; + + return this->service.async_resolve(this->implementation, e, + ASIO_MOVE_CAST(ResolveHandler)(handler)); + } +}; + +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IP_BASIC_RESOLVER_HPP diff --git a/asio-1.10.6/include/asio/ip/basic_resolver_entry.hpp b/asio-1.10.6/include/asio/ip/basic_resolver_entry.hpp new file mode 100644 index 0000000..3d4a61f --- /dev/null +++ b/asio-1.10.6/include/asio/ip/basic_resolver_entry.hpp @@ -0,0 +1,91 @@ +// +// ip/basic_resolver_entry.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_BASIC_RESOLVER_ENTRY_HPP +#define ASIO_IP_BASIC_RESOLVER_ENTRY_HPP + + +#include "asio/detail/config.hpp" +#include <string> + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { + +/// An entry produced by a resolver. +/** + * The asio::ip::basic_resolver_entry class template describes an entry + * as returned by a resolver. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template <typename InternetProtocol> +class basic_resolver_entry +{ +public: + /// The protocol type associated with the endpoint entry. + typedef InternetProtocol protocol_type; + + /// The endpoint type associated with the endpoint entry. + typedef typename InternetProtocol::endpoint endpoint_type; + + /// Default constructor. + basic_resolver_entry() + { + } + + /// Construct with specified endpoint, host name and service name. + basic_resolver_entry(const endpoint_type& ep, + const std::string& host, const std::string& service) + : endpoint_(ep), + host_name_(host), + service_name_(service) + { + } + + /// Get the endpoint associated with the entry. + endpoint_type endpoint() const + { + return endpoint_; + } + + /// Convert to the endpoint associated with the entry. + operator endpoint_type() const + { + return endpoint_; + } + + /// Get the host name associated with the entry. + std::string host_name() const + { + return host_name_; + } + + /// Get the service name associated with the entry. + std::string service_name() const + { + return service_name_; + } + +private: + endpoint_type endpoint_; + std::string host_name_; + std::string service_name_; +}; + +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IP_BASIC_RESOLVER_ENTRY_HPP diff --git a/asio-1.10.6/include/asio/ip/basic_resolver_iterator.hpp b/asio-1.10.6/include/asio/ip/basic_resolver_iterator.hpp new file mode 100644 index 0000000..8e468ff --- /dev/null +++ b/asio-1.10.6/include/asio/ip/basic_resolver_iterator.hpp @@ -0,0 +1,214 @@ +// +// ip/basic_resolver_iterator.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_BASIC_RESOLVER_ITERATOR_HPP +#define ASIO_IP_BASIC_RESOLVER_ITERATOR_HPP + + +#include "asio/detail/config.hpp" +#include <cstddef> +#include <cstring> +#include <iterator> +#include <string> +#include <vector> +#include "asio/detail/shared_ptr.hpp" +#include "asio/detail/socket_ops.hpp" +#include "asio/detail/socket_types.hpp" +#include "asio/ip/basic_resolver_entry.hpp" + + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { + +/// An iterator over the entries produced by a resolver. +/** + * The asio::ip::basic_resolver_iterator class template is used to define + * iterators over the results returned by a resolver. + * + * The iterator's value_type, obtained when the iterator is dereferenced, is: + * @code const basic_resolver_entry<InternetProtocol> @endcode + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template <typename InternetProtocol> +class basic_resolver_iterator +{ +public: + /// The type used for the distance between two iterators. + typedef std::ptrdiff_t difference_type; + + /// The type of the value pointed to by the iterator. + typedef basic_resolver_entry<InternetProtocol> value_type; + + /// The type of the result of applying operator->() to the iterator. + typedef const basic_resolver_entry<InternetProtocol>* pointer; + + /// The type of the result of applying operator*() to the iterator. + typedef const basic_resolver_entry<InternetProtocol>& reference; + + /// The iterator category. + typedef std::forward_iterator_tag iterator_category; + + /// Default constructor creates an end iterator. + basic_resolver_iterator() + : index_(0) + { + } + + /// Create an iterator from an addrinfo list returned by getaddrinfo. + static basic_resolver_iterator create( + asio::detail::addrinfo_type* address_info, + const std::string& host_name, const std::string& service_name) + { + basic_resolver_iterator iter; + if (!address_info) + return iter; + + std::string actual_host_name = host_name; + if (address_info->ai_canonname) + actual_host_name = address_info->ai_canonname; + + iter.values_.reset(new values_type); + + while (address_info) + { + if (address_info->ai_family == ASIO_OS_DEF(AF_INET) + || address_info->ai_family == ASIO_OS_DEF(AF_INET6)) + { + using namespace std; // For memcpy. + typename InternetProtocol::endpoint endpoint; + endpoint.resize(static_cast<std::size_t>(address_info->ai_addrlen)); + memcpy(endpoint.data(), address_info->ai_addr, + address_info->ai_addrlen); + iter.values_->push_back( + basic_resolver_entry<InternetProtocol>(endpoint, + actual_host_name, service_name)); + } + address_info = address_info->ai_next; + } + + return iter; + } + + /// Create an iterator from an endpoint, host name and service name. + static basic_resolver_iterator create( + const typename InternetProtocol::endpoint& endpoint, + const std::string& host_name, const std::string& service_name) + { + basic_resolver_iterator iter; + iter.values_.reset(new values_type); + iter.values_->push_back( + basic_resolver_entry<InternetProtocol>( + endpoint, host_name, service_name)); + return iter; + } + + /// Create an iterator from a sequence of endpoints, host and service name. + template <typename EndpointIterator> + static basic_resolver_iterator create( + EndpointIterator begin, EndpointIterator end, + const std::string& host_name, const std::string& service_name) + { + basic_resolver_iterator iter; + if (begin != end) + { + iter.values_.reset(new values_type); + for (EndpointIterator ep_iter = begin; ep_iter != end; ++ep_iter) + { + iter.values_->push_back( + basic_resolver_entry<InternetProtocol>( + *ep_iter, host_name, service_name)); + } + } + return iter; + } + + + /// Dereference an iterator. + const basic_resolver_entry<InternetProtocol>& operator*() const + { + return dereference(); + } + + /// Dereference an iterator. + const basic_resolver_entry<InternetProtocol>* operator->() const + { + return &dereference(); + } + + /// Increment operator (prefix). + basic_resolver_iterator& operator++() + { + increment(); + return *this; + } + + /// Increment operator (postfix). + basic_resolver_iterator operator++(int) + { + basic_resolver_iterator tmp(*this); + ++*this; + return tmp; + } + + /// Test two iterators for equality. + friend bool operator==(const basic_resolver_iterator& a, + const basic_resolver_iterator& b) + { + return a.equal(b); + } + + /// Test two iterators for inequality. + friend bool operator!=(const basic_resolver_iterator& a, + const basic_resolver_iterator& b) + { + return !a.equal(b); + } + +private: + void increment() + { + if (++index_ == values_->size()) + { + // Reset state to match a default constructed end iterator. + values_.reset(); + index_ = 0; + } + } + + bool equal(const basic_resolver_iterator& other) const + { + if (!values_ && !other.values_) + return true; + if (values_ != other.values_) + return false; + return index_ == other.index_; + } + + const basic_resolver_entry<InternetProtocol>& dereference() const + { + return (*values_)[index_]; + } + + typedef std::vector<basic_resolver_entry<InternetProtocol> > values_type; + asio::detail::shared_ptr<values_type> values_; + std::size_t index_; +}; + +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IP_BASIC_RESOLVER_ITERATOR_HPP diff --git a/asio-1.10.6/include/asio/ip/basic_resolver_query.hpp b/asio-1.10.6/include/asio/ip/basic_resolver_query.hpp new file mode 100644 index 0000000..86c33cc --- /dev/null +++ b/asio-1.10.6/include/asio/ip/basic_resolver_query.hpp @@ -0,0 +1,241 @@ +// +// ip/basic_resolver_query.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_BASIC_RESOLVER_QUERY_HPP +#define ASIO_IP_BASIC_RESOLVER_QUERY_HPP + + +#include "asio/detail/config.hpp" +#include <string> +#include "asio/detail/socket_ops.hpp" +#include "asio/ip/resolver_query_base.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { + +/// An query to be passed to a resolver. +/** + * The asio::ip::basic_resolver_query class template describes a query + * that can be passed to a resolver. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template <typename InternetProtocol> +class basic_resolver_query + : public resolver_query_base +{ +public: + /// The protocol type associated with the endpoint query. + typedef InternetProtocol protocol_type; + + /// Construct with specified service name for any protocol. + /** + * This constructor is typically used to perform name resolution for local + * service binding. + * + * @param service A string identifying the requested service. This may be a + * descriptive name or a numeric string corresponding to a port number. + * + * @param resolve_flags A set of flags that determine how name resolution + * should be performed. The default flags are suitable for local service + * binding. + * + * @note On POSIX systems, service names are typically defined in the file + * <tt>/etc/services</tt>. On Windows, service names may be found in the file + * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems + * may use additional locations when resolving service names. + */ + basic_resolver_query(const std::string& service, + resolver_query_base::flags resolve_flags = passive | address_configured) + : hints_(), + host_name_(), + service_name_(service) + { + typename InternetProtocol::endpoint endpoint; + hints_.ai_flags = static_cast<int>(resolve_flags); + hints_.ai_family = PF_UNSPEC; + hints_.ai_socktype = endpoint.protocol().type(); + hints_.ai_protocol = endpoint.protocol().protocol(); + hints_.ai_addrlen = 0; + hints_.ai_canonname = 0; + hints_.ai_addr = 0; + hints_.ai_next = 0; + } + + /// Construct with specified service name for a given protocol. + /** + * This constructor is typically used to perform name resolution for local + * service binding with a specific protocol version. + * + * @param protocol A protocol object, normally representing either the IPv4 or + * IPv6 version of an internet protocol. + * + * @param service A string identifying the requested service. This may be a + * descriptive name or a numeric string corresponding to a port number. + * + * @param resolve_flags A set of flags that determine how name resolution + * should be performed. The default flags are suitable for local service + * binding. + * + * @note On POSIX systems, service names are typically defined in the file + * <tt>/etc/services</tt>. On Windows, service names may be found in the file + * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems + * may use additional locations when resolving service names. + */ + basic_resolver_query(const protocol_type& protocol, + const std::string& service, + resolver_query_base::flags resolve_flags = passive | address_configured) + : hints_(), + host_name_(), + service_name_(service) + { + hints_.ai_flags = static_cast<int>(resolve_flags); + hints_.ai_family = protocol.family(); + hints_.ai_socktype = protocol.type(); + hints_.ai_protocol = protocol.protocol(); + hints_.ai_addrlen = 0; + hints_.ai_canonname = 0; + hints_.ai_addr = 0; + hints_.ai_next = 0; + } + + /// Construct with specified host name and service name for any protocol. + /** + * This constructor is typically used to perform name resolution for + * communication with remote hosts. + * + * @param host A string identifying a location. May be a descriptive name or + * a numeric address string. If an empty string and the passive flag has been + * specified, the resolved endpoints are suitable for local service binding. + * If an empty string and passive is not specified, the resolved endpoints + * will use the loopback address. + * + * @param service A string identifying the requested service. This may be a + * descriptive name or a numeric string corresponding to a port number. May + * be an empty string, in which case all resolved endpoints will have a port + * number of 0. + * + * @param resolve_flags A set of flags that determine how name resolution + * should be performed. The default flags are suitable for communication with + * remote hosts. + * + * @note On POSIX systems, host names may be locally defined in the file + * <tt>/etc/hosts</tt>. On Windows, host names may be defined in the file + * <tt>c:\\windows\\system32\\drivers\\etc\\hosts</tt>. Remote host name + * resolution is performed using DNS. Operating systems may use additional + * locations when resolving host names (such as NETBIOS names on Windows). + * + * On POSIX systems, service names are typically defined in the file + * <tt>/etc/services</tt>. On Windows, service names may be found in the file + * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems + * may use additional locations when resolving service names. + */ + basic_resolver_query(const std::string& host, const std::string& service, + resolver_query_base::flags resolve_flags = address_configured) + : hints_(), + host_name_(host), + service_name_(service) + { + typename InternetProtocol::endpoint endpoint; + hints_.ai_flags = static_cast<int>(resolve_flags); + hints_.ai_family = ASIO_OS_DEF(AF_UNSPEC); + hints_.ai_socktype = endpoint.protocol().type(); + hints_.ai_protocol = endpoint.protocol().protocol(); + hints_.ai_addrlen = 0; + hints_.ai_canonname = 0; + hints_.ai_addr = 0; + hints_.ai_next = 0; + } + + /// Construct with specified host name and service name for a given protocol. + /** + * This constructor is typically used to perform name resolution for + * communication with remote hosts. + * + * @param protocol A protocol object, normally representing either the IPv4 or + * IPv6 version of an internet protocol. + * + * @param host A string identifying a location. May be a descriptive name or + * a numeric address string. If an empty string and the passive flag has been + * specified, the resolved endpoints are suitable for local service binding. + * If an empty string and passive is not specified, the resolved endpoints + * will use the loopback address. + * + * @param service A string identifying the requested service. This may be a + * descriptive name or a numeric string corresponding to a port number. May + * be an empty string, in which case all resolved endpoints will have a port + * number of 0. + * + * @param resolve_flags A set of flags that determine how name resolution + * should be performed. The default flags are suitable for communication with + * remote hosts. + * + * @note On POSIX systems, host names may be locally defined in the file + * <tt>/etc/hosts</tt>. On Windows, host names may be defined in the file + * <tt>c:\\windows\\system32\\drivers\\etc\\hosts</tt>. Remote host name + * resolution is performed using DNS. Operating systems may use additional + * locations when resolving host names (such as NETBIOS names on Windows). + * + * On POSIX systems, service names are typically defined in the file + * <tt>/etc/services</tt>. On Windows, service names may be found in the file + * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems + * may use additional locations when resolving service names. + */ + basic_resolver_query(const protocol_type& protocol, + const std::string& host, const std::string& service, + resolver_query_base::flags resolve_flags = address_configured) + : hints_(), + host_name_(host), + service_name_(service) + { + hints_.ai_flags = static_cast<int>(resolve_flags); + hints_.ai_family = protocol.family(); + hints_.ai_socktype = protocol.type(); + hints_.ai_protocol = protocol.protocol(); + hints_.ai_addrlen = 0; + hints_.ai_canonname = 0; + hints_.ai_addr = 0; + hints_.ai_next = 0; + } + + /// Get the hints associated with the query. + const asio::detail::addrinfo_type& hints() const + { + return hints_; + } + + /// Get the host name associated with the query. + std::string host_name() const + { + return host_name_; + } + + /// Get the service name associated with the query. + std::string service_name() const + { + return service_name_; + } + +private: + asio::detail::addrinfo_type hints_; + std::string host_name_; + std::string service_name_; +}; + +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IP_BASIC_RESOLVER_QUERY_HPP diff --git a/asio-1.10.6/include/asio/ip/detail/endpoint.hpp b/asio-1.10.6/include/asio/ip/detail/endpoint.hpp new file mode 100644 index 0000000..cbf188c --- /dev/null +++ b/asio-1.10.6/include/asio/ip/detail/endpoint.hpp @@ -0,0 +1,130 @@ +// +// ip/detail/endpoint.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_DETAIL_ENDPOINT_HPP +#define ASIO_IP_DETAIL_ENDPOINT_HPP + + +#include "asio/detail/config.hpp" +#include <string> +#include "asio/detail/socket_types.hpp" +#include "asio/detail/winsock_init.hpp" +#include "asio/error_code.hpp" +#include "asio/ip/address.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { +namespace detail { + +// Helper class for implementating an IP endpoint. +class endpoint +{ +public: + // Default constructor. + ASIO_DECL endpoint(); + + // Construct an endpoint using a family and port number. + ASIO_DECL endpoint(int family, unsigned short port_num); + + // Construct an endpoint using an address and port number. + ASIO_DECL endpoint(const asio::ip::address& addr, + unsigned short port_num); + + // Copy constructor. + endpoint(const endpoint& other) + : data_(other.data_) + { + } + + // Assign from another endpoint. + endpoint& operator=(const endpoint& other) + { + data_ = other.data_; + return *this; + } + + // Get the underlying endpoint in the native type. + asio::detail::socket_addr_type* data() + { + return &data_.base; + } + + // Get the underlying endpoint in the native type. + const asio::detail::socket_addr_type* data() const + { + return &data_.base; + } + + // Get the underlying size of the endpoint in the native type. + std::size_t size() const + { + if (is_v4()) + return sizeof(asio::detail::sockaddr_in4_type); + else + return sizeof(asio::detail::sockaddr_in6_type); + } + + // Set the underlying size of the endpoint in the native type. + ASIO_DECL void resize(std::size_t new_size); + + // Get the capacity of the endpoint in the native type. + std::size_t capacity() const + { + return sizeof(data_); + } + + // Get the port associated with the endpoint. + ASIO_DECL unsigned short port() const; + + // Set the port associated with the endpoint. + ASIO_DECL void port(unsigned short port_num); + + // Get the IP address associated with the endpoint. + ASIO_DECL asio::ip::address address() const; + + // Set the IP address associated with the endpoint. + ASIO_DECL void address(const asio::ip::address& addr); + + // Compare two endpoints for equality. + ASIO_DECL friend bool operator==( + const endpoint& e1, const endpoint& e2); + + // Compare endpoints for ordering. + ASIO_DECL friend bool operator<( + const endpoint& e1, const endpoint& e2); + + // Determine whether the endpoint is IPv4. + bool is_v4() const + { + return data_.base.sa_family == ASIO_OS_DEF(AF_INET); + } + + +private: + // The underlying IP socket address. + union data_union + { + asio::detail::socket_addr_type base; + asio::detail::sockaddr_in4_type v4; + asio::detail::sockaddr_in6_type v6; + } data_; +}; + +} // namespace detail +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +# include "asio/ip/detail/impl/endpoint.ipp" + +#endif // ASIO_IP_DETAIL_ENDPOINT_HPP diff --git a/asio-1.10.6/include/asio/ip/detail/impl/endpoint.ipp b/asio-1.10.6/include/asio/ip/detail/impl/endpoint.ipp new file mode 100644 index 0000000..2988d7e --- /dev/null +++ b/asio-1.10.6/include/asio/ip/detail/impl/endpoint.ipp @@ -0,0 +1,176 @@ +// +// ip/detail/impl/endpoint.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_DETAIL_IMPL_ENDPOINT_IPP +#define ASIO_IP_DETAIL_IMPL_ENDPOINT_IPP + + +#include "asio/detail/config.hpp" +#include <cstring> +#include "asio/detail/socket_ops.hpp" +#include "asio/detail/throw_error.hpp" +#include "asio/error.hpp" +#include "asio/ip/detail/endpoint.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { +namespace detail { + +endpoint::endpoint() + : data_() +{ + data_.v4.sin_family = ASIO_OS_DEF(AF_INET); + data_.v4.sin_port = 0; + data_.v4.sin_addr.s_addr = ASIO_OS_DEF(INADDR_ANY); +} + +endpoint::endpoint(int family, unsigned short port_num) + : data_() +{ + using namespace std; // For memcpy. + if (family == ASIO_OS_DEF(AF_INET)) + { + data_.v4.sin_family = ASIO_OS_DEF(AF_INET); + data_.v4.sin_port = + asio::detail::socket_ops::host_to_network_short(port_num); + data_.v4.sin_addr.s_addr = ASIO_OS_DEF(INADDR_ANY); + } + else + { + data_.v6.sin6_family = ASIO_OS_DEF(AF_INET6); + data_.v6.sin6_port = + asio::detail::socket_ops::host_to_network_short(port_num); + data_.v6.sin6_flowinfo = 0; + data_.v6.sin6_addr.s6_addr[0] = 0; data_.v6.sin6_addr.s6_addr[1] = 0; + data_.v6.sin6_addr.s6_addr[2] = 0, data_.v6.sin6_addr.s6_addr[3] = 0; + data_.v6.sin6_addr.s6_addr[4] = 0, data_.v6.sin6_addr.s6_addr[5] = 0; + data_.v6.sin6_addr.s6_addr[6] = 0, data_.v6.sin6_addr.s6_addr[7] = 0; + data_.v6.sin6_addr.s6_addr[8] = 0, data_.v6.sin6_addr.s6_addr[9] = 0; + data_.v6.sin6_addr.s6_addr[10] = 0, data_.v6.sin6_addr.s6_addr[11] = 0; + data_.v6.sin6_addr.s6_addr[12] = 0, data_.v6.sin6_addr.s6_addr[13] = 0; + data_.v6.sin6_addr.s6_addr[14] = 0, data_.v6.sin6_addr.s6_addr[15] = 0; + data_.v6.sin6_scope_id = 0; + } +} + +endpoint::endpoint(const asio::ip::address& addr, + unsigned short port_num) + : data_() +{ + using namespace std; // For memcpy. + if (addr.is_v4()) + { + data_.v4.sin_family = ASIO_OS_DEF(AF_INET); + data_.v4.sin_port = + asio::detail::socket_ops::host_to_network_short(port_num); + data_.v4.sin_addr.s_addr = + asio::detail::socket_ops::host_to_network_long( + static_cast<asio::detail::u_long_type>( + addr.to_v4().to_ulong())); + } + else + { + data_.v6.sin6_family = ASIO_OS_DEF(AF_INET6); + data_.v6.sin6_port = + asio::detail::socket_ops::host_to_network_short(port_num); + data_.v6.sin6_flowinfo = 0; + asio::ip::address_v6 v6_addr = addr.to_v6(); + asio::ip::address_v6::bytes_type bytes = v6_addr.to_bytes(); + memcpy(data_.v6.sin6_addr.s6_addr, bytes.data(), 16); + data_.v6.sin6_scope_id = + static_cast<asio::detail::u_long_type>( + v6_addr.scope_id()); + } +} + +void endpoint::resize(std::size_t new_size) +{ + if (new_size > sizeof(asio::detail::sockaddr_storage_type)) + { + asio::error_code ec(asio::error::invalid_argument); + asio::detail::throw_error(ec); + } +} + +unsigned short endpoint::port() const +{ + if (is_v4()) + { + return asio::detail::socket_ops::network_to_host_short( + data_.v4.sin_port); + } + else + { + return asio::detail::socket_ops::network_to_host_short( + data_.v6.sin6_port); + } +} + +void endpoint::port(unsigned short port_num) +{ + if (is_v4()) + { + data_.v4.sin_port + = asio::detail::socket_ops::host_to_network_short(port_num); + } + else + { + data_.v6.sin6_port + = asio::detail::socket_ops::host_to_network_short(port_num); + } +} + +asio::ip::address endpoint::address() const +{ + using namespace std; // For memcpy. + if (is_v4()) + { + return asio::ip::address_v4( + asio::detail::socket_ops::network_to_host_long( + data_.v4.sin_addr.s_addr)); + } + else + { + asio::ip::address_v6::bytes_type bytes; + memcpy(bytes.data(), data_.v6.sin6_addr.s6_addr, 16); + return asio::ip::address_v6(bytes, data_.v6.sin6_scope_id); + } +} + +void endpoint::address(const asio::ip::address& addr) +{ + endpoint tmp_endpoint(addr, port()); + data_ = tmp_endpoint.data_; +} + +bool operator==(const endpoint& e1, const endpoint& e2) +{ + return e1.address() == e2.address() && e1.port() == e2.port(); +} + +bool operator<(const endpoint& e1, const endpoint& e2) +{ + if (e1.address() < e2.address()) + return true; + if (e1.address() != e2.address()) + return false; + return e1.port() < e2.port(); +} + + +} // namespace detail +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IP_DETAIL_IMPL_ENDPOINT_IPP diff --git a/asio-1.10.6/include/asio/ip/impl/address.hpp b/asio-1.10.6/include/asio/ip/impl/address.hpp new file mode 100644 index 0000000..d16c7be --- /dev/null +++ b/asio-1.10.6/include/asio/ip/impl/address.hpp @@ -0,0 +1,16 @@ +// +// ip/impl/address.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_IMPL_ADDRESS_HPP +#define ASIO_IP_IMPL_ADDRESS_HPP + + + +#endif // ASIO_IP_IMPL_ADDRESS_HPP diff --git a/asio-1.10.6/include/asio/ip/impl/address.ipp b/asio-1.10.6/include/asio/ip/impl/address.ipp new file mode 100644 index 0000000..b52ad3d --- /dev/null +++ b/asio-1.10.6/include/asio/ip/impl/address.ipp @@ -0,0 +1,219 @@ +// +// ip/impl/address.ipp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_IMPL_ADDRESS_IPP +#define ASIO_IP_IMPL_ADDRESS_IPP + + +#include "asio/detail/config.hpp" +#include <typeinfo> +#include "asio/detail/throw_error.hpp" +#include "asio/detail/throw_exception.hpp" +#include "asio/error.hpp" +#include "asio/ip/address.hpp" +#include "asio/system_error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { + +address::address() + : type_(ipv4), + ipv4_address_(), + ipv6_address_() +{ +} + +address::address(const asio::ip::address_v4& ipv4_address) + : type_(ipv4), + ipv4_address_(ipv4_address), + ipv6_address_() +{ +} + +address::address(const asio::ip::address_v6& ipv6_address) + : type_(ipv6), + ipv4_address_(), + ipv6_address_(ipv6_address) +{ +} + +address::address(const address& other) + : type_(other.type_), + ipv4_address_(other.ipv4_address_), + ipv6_address_(other.ipv6_address_) +{ +} + +address::address(address&& other) + : type_(other.type_), + ipv4_address_(other.ipv4_address_), + ipv6_address_(other.ipv6_address_) +{ +} + +address& address::operator=(const address& other) +{ + type_ = other.type_; + ipv4_address_ = other.ipv4_address_; + ipv6_address_ = other.ipv6_address_; + return *this; +} + +address& address::operator=(address&& other) +{ + type_ = other.type_; + ipv4_address_ = other.ipv4_address_; + ipv6_address_ = other.ipv6_address_; + return *this; +} + +address& address::operator=(const asio::ip::address_v4& ipv4_address) +{ + type_ = ipv4; + ipv4_address_ = ipv4_address; + ipv6_address_ = asio::ip::address_v6(); + return *this; +} + +address& address::operator=(const asio::ip::address_v6& ipv6_address) +{ + type_ = ipv6; + ipv4_address_ = asio::ip::address_v4(); + ipv6_address_ = ipv6_address; + return *this; +} + +asio::ip::address_v4 address::to_v4() const +{ + if (type_ != ipv4) + { + std::bad_cast ex; + asio::detail::throw_exception(ex); + } + return ipv4_address_; +} + +asio::ip::address_v6 address::to_v6() const +{ + if (type_ != ipv6) + { + std::bad_cast ex; + asio::detail::throw_exception(ex); + } + return ipv6_address_; +} + +std::string address::to_string() const +{ + if (type_ == ipv6) + return ipv6_address_.to_string(); + return ipv4_address_.to_string(); +} + +std::string address::to_string(asio::error_code& ec) const +{ + if (type_ == ipv6) + return ipv6_address_.to_string(ec); + return ipv4_address_.to_string(ec); +} + +address address::from_string(const char* str) +{ + asio::error_code ec; + address addr = from_string(str, ec); + asio::detail::throw_error(ec); + return addr; +} + +address address::from_string(const char* str, asio::error_code& ec) +{ + asio::ip::address_v6 ipv6_address = + asio::ip::address_v6::from_string(str, ec); + if (!ec) + { + address tmp; + tmp.type_ = ipv6; + tmp.ipv6_address_ = ipv6_address; + return tmp; + } + + asio::ip::address_v4 ipv4_address = + asio::ip::address_v4::from_string(str, ec); + if (!ec) + { + address tmp; + tmp.type_ = ipv4; + tmp.ipv4_address_ = ipv4_address; + return tmp; + } + + return address(); +} + +address address::from_string(const std::string& str) +{ + return from_string(str.c_str()); +} + +address address::from_string(const std::string& str, + asio::error_code& ec) +{ + return from_string(str.c_str(), ec); +} + +bool address::is_loopback() const +{ + return (type_ == ipv4) + ? ipv4_address_.is_loopback() + : ipv6_address_.is_loopback(); +} + +bool address::is_unspecified() const +{ + return (type_ == ipv4) + ? ipv4_address_.is_unspecified() + : ipv6_address_.is_unspecified(); +} + +bool address::is_multicast() const +{ + return (type_ == ipv4) + ? ipv4_address_.is_multicast() + : ipv6_address_.is_multicast(); +} + +bool operator==(const address& a1, const address& a2) +{ + if (a1.type_ != a2.type_) + return false; + if (a1.type_ == address::ipv6) + return a1.ipv6_address_ == a2.ipv6_address_; + return a1.ipv4_address_ == a2.ipv4_address_; +} + +bool operator<(const address& a1, const address& a2) +{ + if (a1.type_ < a2.type_) + return true; + if (a1.type_ > a2.type_) + return false; + if (a1.type_ == address::ipv6) + return a1.ipv6_address_ < a2.ipv6_address_; + return a1.ipv4_address_ < a2.ipv4_address_; +} + +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IP_IMPL_ADDRESS_IPP diff --git a/asio-1.10.6/include/asio/ip/impl/address_v4.hpp b/asio-1.10.6/include/asio/ip/impl/address_v4.hpp new file mode 100644 index 0000000..86e993a --- /dev/null +++ b/asio-1.10.6/include/asio/ip/impl/address_v4.hpp @@ -0,0 +1,16 @@ +// +// ip/impl/address_v4.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_IMPL_ADDRESS_V4_HPP +#define ASIO_IP_IMPL_ADDRESS_V4_HPP + + + +#endif // ASIO_IP_IMPL_ADDRESS_V4_HPP diff --git a/asio-1.10.6/include/asio/ip/impl/address_v4.ipp b/asio-1.10.6/include/asio/ip/impl/address_v4.ipp new file mode 100644 index 0000000..1ff5944 --- /dev/null +++ b/asio-1.10.6/include/asio/ip/impl/address_v4.ipp @@ -0,0 +1,171 @@ +// +// ip/impl/address_v4.ipp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_IMPL_ADDRESS_V4_IPP +#define ASIO_IP_IMPL_ADDRESS_V4_IPP + + +#include "asio/detail/config.hpp" +#include <climits> +#include <stdexcept> +#include "asio/error.hpp" +#include "asio/detail/socket_ops.hpp" +#include "asio/detail/throw_error.hpp" +#include "asio/detail/throw_exception.hpp" +#include "asio/ip/address_v4.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { + +address_v4::address_v4(const address_v4::bytes_type& bytes) +{ +#if UCHAR_MAX > 0xFF + if (bytes[0] > 0xFF || bytes[1] > 0xFF + || bytes[2] > 0xFF || bytes[3] > 0xFF) + { + std::out_of_range ex("address_v4 from bytes_type"); + asio::detail::throw_exception(ex); + } +#endif // UCHAR_MAX > 0xFF + + using namespace std; // For memcpy. + memcpy(&addr_.s_addr, bytes.data(), 4); +} + +address_v4::address_v4(unsigned long addr) +{ +#if ULONG_MAX > 0xFFFFFFFF + if (addr > 0xFFFFFFFF) + { + std::out_of_range ex("address_v4 from unsigned long"); + asio::detail::throw_exception(ex); + } +#endif // ULONG_MAX > 0xFFFFFFFF + + addr_.s_addr = asio::detail::socket_ops::host_to_network_long( + static_cast<asio::detail::u_long_type>(addr)); +} + +address_v4::bytes_type address_v4::to_bytes() const +{ + using namespace std; // For memcpy. + bytes_type bytes; + memcpy(bytes.data(), &addr_.s_addr, 4); + return bytes; +} + +unsigned long address_v4::to_ulong() const +{ + return asio::detail::socket_ops::network_to_host_long(addr_.s_addr); +} + +std::string address_v4::to_string() const +{ + asio::error_code ec; + std::string addr = to_string(ec); + asio::detail::throw_error(ec); + return addr; +} + +std::string address_v4::to_string(asio::error_code& ec) const +{ + char addr_str[asio::detail::max_addr_v4_str_len]; + const char* addr = + asio::detail::socket_ops::inet_ntop( + ASIO_OS_DEF(AF_INET), &addr_, addr_str, + asio::detail::max_addr_v4_str_len, 0, ec); + if (addr == 0) + return std::string(); + return addr; +} + +address_v4 address_v4::from_string(const char* str) +{ + asio::error_code ec; + address_v4 addr = from_string(str, ec); + asio::detail::throw_error(ec); + return addr; +} + +address_v4 address_v4::from_string( + const char* str, asio::error_code& ec) +{ + address_v4 tmp; + if (asio::detail::socket_ops::inet_pton( + ASIO_OS_DEF(AF_INET), str, &tmp.addr_, 0, ec) <= 0) + return address_v4(); + return tmp; +} + +address_v4 address_v4::from_string(const std::string& str) +{ + return from_string(str.c_str()); +} + +address_v4 address_v4::from_string( + const std::string& str, asio::error_code& ec) +{ + return from_string(str.c_str(), ec); +} + +bool address_v4::is_loopback() const +{ + return (to_ulong() & 0xFF000000) == 0x7F000000; +} + +bool address_v4::is_unspecified() const +{ + return to_ulong() == 0; +} + +bool address_v4::is_class_a() const +{ + return (to_ulong() & 0x80000000) == 0; +} + +bool address_v4::is_class_b() const +{ + return (to_ulong() & 0xC0000000) == 0x80000000; +} + +bool address_v4::is_class_c() const +{ + return (to_ulong() & 0xE0000000) == 0xC0000000; +} + +bool address_v4::is_multicast() const +{ + return (to_ulong() & 0xF0000000) == 0xE0000000; +} + +address_v4 address_v4::broadcast(const address_v4& addr, const address_v4& mask) +{ + return address_v4(addr.to_ulong() | (mask.to_ulong() ^ 0xFFFFFFFF)); +} + +address_v4 address_v4::netmask(const address_v4& addr) +{ + if (addr.is_class_a()) + return address_v4(0xFF000000); + if (addr.is_class_b()) + return address_v4(0xFFFF0000); + if (addr.is_class_c()) + return address_v4(0xFFFFFF00); + return address_v4(0xFFFFFFFF); +} + +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IP_IMPL_ADDRESS_V4_IPP diff --git a/asio-1.10.6/include/asio/ip/impl/address_v6.hpp b/asio-1.10.6/include/asio/ip/impl/address_v6.hpp new file mode 100644 index 0000000..9637a8f --- /dev/null +++ b/asio-1.10.6/include/asio/ip/impl/address_v6.hpp @@ -0,0 +1,16 @@ +// +// ip/impl/address_v6.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_IMPL_ADDRESS_V6_HPP +#define ASIO_IP_IMPL_ADDRESS_V6_HPP + + + +#endif // ASIO_IP_IMPL_ADDRESS_V6_HPP diff --git a/asio-1.10.6/include/asio/ip/impl/address_v6.ipp b/asio-1.10.6/include/asio/ip/impl/address_v6.ipp new file mode 100644 index 0000000..339e4a7 --- /dev/null +++ b/asio-1.10.6/include/asio/ip/impl/address_v6.ipp @@ -0,0 +1,287 @@ +// +// ip/impl/address_v6.ipp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_IMPL_ADDRESS_V6_IPP +#define ASIO_IP_IMPL_ADDRESS_V6_IPP + + +#include "asio/detail/config.hpp" +#include <cstring> +#include <stdexcept> +#include <typeinfo> +#include "asio/detail/socket_ops.hpp" +#include "asio/detail/throw_error.hpp" +#include "asio/detail/throw_exception.hpp" +#include "asio/error.hpp" +#include "asio/ip/address_v6.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { + +address_v6::address_v6() + : addr_(), + scope_id_(0) +{ +} + +address_v6::address_v6(const address_v6::bytes_type& bytes, + unsigned long scope) + : scope_id_(scope) +{ +#if UCHAR_MAX > 0xFF + for (std::size_t i = 0; i < bytes.size(); ++i) + { + if (bytes[i] > 0xFF) + { + std::out_of_range ex("address_v6 from bytes_type"); + asio::detail::throw_exception(ex); + } + } +#endif // UCHAR_MAX > 0xFF + + using namespace std; // For memcpy. + memcpy(addr_.s6_addr, bytes.data(), 16); +} + +address_v6::address_v6(const address_v6& other) + : addr_(other.addr_), + scope_id_(other.scope_id_) +{ +} + +address_v6::address_v6(address_v6&& other) + : addr_(other.addr_), + scope_id_(other.scope_id_) +{ +} + +address_v6& address_v6::operator=(const address_v6& other) +{ + addr_ = other.addr_; + scope_id_ = other.scope_id_; + return *this; +} + +address_v6& address_v6::operator=(address_v6&& other) +{ + addr_ = other.addr_; + scope_id_ = other.scope_id_; + return *this; +} + +address_v6::bytes_type address_v6::to_bytes() const +{ + using namespace std; // For memcpy. + bytes_type bytes; + memcpy(bytes.data(), addr_.s6_addr, 16); + return bytes; +} + +std::string address_v6::to_string() const +{ + asio::error_code ec; + std::string addr = to_string(ec); + asio::detail::throw_error(ec); + return addr; +} + +std::string address_v6::to_string(asio::error_code& ec) const +{ + char addr_str[asio::detail::max_addr_v6_str_len]; + const char* addr = + asio::detail::socket_ops::inet_ntop( + ASIO_OS_DEF(AF_INET6), &addr_, addr_str, + asio::detail::max_addr_v6_str_len, scope_id_, ec); + if (addr == 0) + return std::string(); + return addr; +} + +address_v6 address_v6::from_string(const char* str) +{ + asio::error_code ec; + address_v6 addr = from_string(str, ec); + asio::detail::throw_error(ec); + return addr; +} + +address_v6 address_v6::from_string( + const char* str, asio::error_code& ec) +{ + address_v6 tmp; + if (asio::detail::socket_ops::inet_pton( + ASIO_OS_DEF(AF_INET6), str, &tmp.addr_, &tmp.scope_id_, ec) <= 0) + return address_v6(); + return tmp; +} + +address_v6 address_v6::from_string(const std::string& str) +{ + return from_string(str.c_str()); +} + +address_v6 address_v6::from_string( + const std::string& str, asio::error_code& ec) +{ + return from_string(str.c_str(), ec); +} + +address_v4 address_v6::to_v4() const +{ + if (!is_v4_mapped() && !is_v4_compatible()) + { + std::bad_cast ex; + asio::detail::throw_exception(ex); + } + + address_v4::bytes_type v4_bytes = { { addr_.s6_addr[12], + addr_.s6_addr[13], addr_.s6_addr[14], addr_.s6_addr[15] } }; + return address_v4(v4_bytes); +} + +bool address_v6::is_loopback() const +{ + return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0) + && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0) + && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0) + && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0) + && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0) + && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0) + && (addr_.s6_addr[12] == 0) && (addr_.s6_addr[13] == 0) + && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 1)); +} + +bool address_v6::is_unspecified() const +{ + return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0) + && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0) + && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0) + && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0) + && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0) + && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0) + && (addr_.s6_addr[12] == 0) && (addr_.s6_addr[13] == 0) + && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 0)); +} + +bool address_v6::is_link_local() const +{ + return ((addr_.s6_addr[0] == 0xfe) && ((addr_.s6_addr[1] & 0xc0) == 0x80)); +} + +bool address_v6::is_site_local() const +{ + return ((addr_.s6_addr[0] == 0xfe) && ((addr_.s6_addr[1] & 0xc0) == 0xc0)); +} + +bool address_v6::is_v4_mapped() const +{ + return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0) + && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0) + && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0) + && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0) + && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0) + && (addr_.s6_addr[10] == 0xff) && (addr_.s6_addr[11] == 0xff)); +} + +bool address_v6::is_v4_compatible() const +{ + return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0) + && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0) + && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0) + && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0) + && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0) + && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0) + && !((addr_.s6_addr[12] == 0) + && (addr_.s6_addr[13] == 0) + && (addr_.s6_addr[14] == 0) + && ((addr_.s6_addr[15] == 0) || (addr_.s6_addr[15] == 1)))); +} + +bool address_v6::is_multicast() const +{ + return (addr_.s6_addr[0] == 0xff); +} + +bool address_v6::is_multicast_global() const +{ + return ((addr_.s6_addr[0] == 0xff) && ((addr_.s6_addr[1] & 0x0f) == 0x0e)); +} + +bool address_v6::is_multicast_link_local() const +{ + return ((addr_.s6_addr[0] == 0xff) && ((addr_.s6_addr[1] & 0x0f) == 0x02)); +} + +bool address_v6::is_multicast_node_local() const +{ + return ((addr_.s6_addr[0] == 0xff) && ((addr_.s6_addr[1] & 0x0f) == 0x01)); +} + +bool address_v6::is_multicast_org_local() const +{ + return ((addr_.s6_addr[0] == 0xff) && ((addr_.s6_addr[1] & 0x0f) == 0x08)); +} + +bool address_v6::is_multicast_site_local() const +{ + return ((addr_.s6_addr[0] == 0xff) && ((addr_.s6_addr[1] & 0x0f) == 0x05)); +} + +bool operator==(const address_v6& a1, const address_v6& a2) +{ + using namespace std; // For memcmp. + return memcmp(&a1.addr_, &a2.addr_, + sizeof(asio::detail::in6_addr_type)) == 0 + && a1.scope_id_ == a2.scope_id_; +} + +bool operator<(const address_v6& a1, const address_v6& a2) +{ + using namespace std; // For memcmp. + int memcmp_result = memcmp(&a1.addr_, &a2.addr_, + sizeof(asio::detail::in6_addr_type)); + if (memcmp_result < 0) + return true; + if (memcmp_result > 0) + return false; + return a1.scope_id_ < a2.scope_id_; +} + +address_v6 address_v6::loopback() +{ + address_v6 tmp; + tmp.addr_.s6_addr[15] = 1; + return tmp; +} + +address_v6 address_v6::v4_mapped(const address_v4& addr) +{ + address_v4::bytes_type v4_bytes = addr.to_bytes(); + bytes_type v6_bytes = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, + v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } }; + return address_v6(v6_bytes); +} + +address_v6 address_v6::v4_compatible(const address_v4& addr) +{ + address_v4::bytes_type v4_bytes = addr.to_bytes(); + bytes_type v6_bytes = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } }; + return address_v6(v6_bytes); +} + +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IP_IMPL_ADDRESS_V6_IPP diff --git a/asio-1.10.6/include/asio/ip/impl/basic_endpoint.hpp b/asio-1.10.6/include/asio/ip/impl/basic_endpoint.hpp new file mode 100644 index 0000000..93d692a --- /dev/null +++ b/asio-1.10.6/include/asio/ip/impl/basic_endpoint.hpp @@ -0,0 +1,16 @@ +// +// ip/impl/basic_endpoint.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_IMPL_BASIC_ENDPOINT_HPP +#define ASIO_IP_IMPL_BASIC_ENDPOINT_HPP + + + +#endif // ASIO_IP_IMPL_BASIC_ENDPOINT_HPP diff --git a/asio-1.10.6/include/asio/ip/resolver_query_base.hpp b/asio-1.10.6/include/asio/ip/resolver_query_base.hpp new file mode 100644 index 0000000..adbf66d --- /dev/null +++ b/asio-1.10.6/include/asio/ip/resolver_query_base.hpp @@ -0,0 +1,95 @@ +// +// ip/resolver_query_base.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_RESOLVER_QUERY_BASE_HPP +#define ASIO_IP_RESOLVER_QUERY_BASE_HPP + + +#include "asio/detail/config.hpp" +#include "asio/detail/socket_types.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { + +/// The resolver_query_base class is used as a base for the +/// basic_resolver_query class templates to provide a common place to define +/// the flag constants. +class resolver_query_base +{ +public: + enum flags + { + canonical_name = ASIO_OS_DEF(AI_CANONNAME), + passive = ASIO_OS_DEF(AI_PASSIVE), + numeric_host = ASIO_OS_DEF(AI_NUMERICHOST), + numeric_service = ASIO_OS_DEF(AI_NUMERICSERV), + v4_mapped = ASIO_OS_DEF(AI_V4MAPPED), + all_matching = ASIO_OS_DEF(AI_ALL), + address_configured = ASIO_OS_DEF(AI_ADDRCONFIG) + }; + + // Implement bitmask operations as shown in C++ Std [lib.bitmask.types]. + + friend flags operator&(flags x, flags y) + { + return static_cast<flags>( + static_cast<unsigned int>(x) & static_cast<unsigned int>(y)); + } + + friend flags operator|(flags x, flags y) + { + return static_cast<flags>( + static_cast<unsigned int>(x) | static_cast<unsigned int>(y)); + } + + friend flags operator^(flags x, flags y) + { + return static_cast<flags>( + static_cast<unsigned int>(x) ^ static_cast<unsigned int>(y)); + } + + friend flags operator~(flags x) + { + return static_cast<flags>(~static_cast<unsigned int>(x)); + } + + friend flags& operator&=(flags& x, flags y) + { + x = x & y; + return x; + } + + friend flags& operator|=(flags& x, flags y) + { + x = x | y; + return x; + } + + friend flags& operator^=(flags& x, flags y) + { + x = x ^ y; + return x; + } + +protected: + /// Protected destructor to prevent deletion through this type. + ~resolver_query_base() + { + } +}; + +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IP_RESOLVER_QUERY_BASE_HPP diff --git a/asio-1.10.6/include/asio/ip/resolver_service.hpp b/asio-1.10.6/include/asio/ip/resolver_service.hpp new file mode 100644 index 0000000..99ac3f3 --- /dev/null +++ b/asio-1.10.6/include/asio/ip/resolver_service.hpp @@ -0,0 +1,152 @@ +// +// ip/resolver_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_RESOLVER_SERVICE_HPP +#define ASIO_IP_RESOLVER_SERVICE_HPP + + +#include "asio/detail/config.hpp" +#include "asio/async_result.hpp" +#include "asio/error_code.hpp" +#include "asio/io_service.hpp" +#include "asio/ip/basic_resolver_iterator.hpp" +#include "asio/ip/basic_resolver_query.hpp" + +# include "asio/detail/resolver_service.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { + +/// Default service implementation for a resolver. +template <typename InternetProtocol> +class resolver_service + : public asio::detail::service_base< + resolver_service<InternetProtocol> > +{ +public: + + /// The protocol type. + typedef InternetProtocol protocol_type; + + /// The endpoint type. + typedef typename InternetProtocol::endpoint endpoint_type; + + /// The query type. + typedef basic_resolver_query<InternetProtocol> query_type; + + /// The iterator type. + typedef basic_resolver_iterator<InternetProtocol> iterator_type; + +private: + // The type of the platform-specific implementation. + typedef asio::detail::resolver_service<InternetProtocol> + service_impl_type; + +public: + /// The type of a resolver implementation. + typedef typename service_impl_type::implementation_type implementation_type; + + /// Construct a new resolver service for the specified io_service. + explicit resolver_service(asio::io_service& io_service) + : asio::detail::service_base< + resolver_service<InternetProtocol> >(io_service), + service_impl_(io_service) + { + } + + /// Construct a new resolver implementation. + void construct(implementation_type& impl) + { + service_impl_.construct(impl); + } + + /// Destroy a resolver implementation. + void destroy(implementation_type& impl) + { + service_impl_.destroy(impl); + } + + /// Cancel pending asynchronous operations. + void cancel(implementation_type& impl) + { + service_impl_.cancel(impl); + } + + /// Resolve a query to a list of entries. + iterator_type resolve(implementation_type& impl, const query_type& query, + asio::error_code& ec) + { + return service_impl_.resolve(impl, query, ec); + } + + /// Asynchronously resolve a query to a list of entries. + template <typename ResolveHandler> + ASIO_INITFN_RESULT_TYPE(ResolveHandler, + void (asio::error_code, iterator_type)) + async_resolve(implementation_type& impl, const query_type& query, + ASIO_MOVE_ARG(ResolveHandler) handler) + { + asio::detail::async_result_init< + ResolveHandler, void (asio::error_code, iterator_type)> init( + ASIO_MOVE_CAST(ResolveHandler)(handler)); + + service_impl_.async_resolve(impl, query, init.handler); + + return init.result.get(); + } + + /// Resolve an endpoint to a list of entries. + iterator_type resolve(implementation_type& impl, + const endpoint_type& endpoint, asio::error_code& ec) + { + return service_impl_.resolve(impl, endpoint, ec); + } + + /// Asynchronously resolve an endpoint to a list of entries. + template <typename ResolveHandler> + ASIO_INITFN_RESULT_TYPE(ResolveHandler, + void (asio::error_code, iterator_type)) + async_resolve(implementation_type& impl, const endpoint_type& endpoint, + ASIO_MOVE_ARG(ResolveHandler) handler) + { + asio::detail::async_result_init< + ResolveHandler, void (asio::error_code, iterator_type)> init( + ASIO_MOVE_CAST(ResolveHandler)(handler)); + + service_impl_.async_resolve(impl, endpoint, init.handler); + + return init.result.get(); + } + +private: + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + service_impl_.shutdown_service(); + } + + // Perform any fork-related housekeeping. + void fork_service(asio::io_service::fork_event event) + { + service_impl_.fork_service(event); + } + + // The platform-specific implementation. + service_impl_type service_impl_; +}; + +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IP_RESOLVER_SERVICE_HPP diff --git a/asio-1.10.6/include/asio/ip/tcp.hpp b/asio-1.10.6/include/asio/ip/tcp.hpp new file mode 100644 index 0000000..0d60f7d --- /dev/null +++ b/asio-1.10.6/include/asio/ip/tcp.hpp @@ -0,0 +1,144 @@ +// +// ip/tcp.hpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_TCP_HPP +#define ASIO_IP_TCP_HPP + + +#include "asio/detail/config.hpp" +#include "asio/basic_socket_acceptor.hpp" +#include "asio/basic_socket_iostream.hpp" +#include "asio/basic_stream_socket.hpp" +#include "asio/detail/socket_option.hpp" +#include "asio/detail/socket_types.hpp" +#include "asio/ip/basic_endpoint.hpp" +#include "asio/ip/basic_resolver.hpp" +#include "asio/ip/basic_resolver_iterator.hpp" +#include "asio/ip/basic_resolver_query.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { + +/// Encapsulates the flags needed for TCP. +/** + * The asio::ip::tcp class contains flags necessary for TCP sockets. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Safe. + * + * @par Concepts: + * Protocol, InternetProtocol. + */ +class tcp +{ +public: + /// The type of a TCP endpoint. + typedef basic_endpoint<tcp> endpoint; + + /// Construct to represent the IPv4 TCP protocol. + static tcp v4() + { + return tcp(ASIO_OS_DEF(AF_INET)); + } + + /// Construct to represent the IPv6 TCP protocol. + static tcp v6() + { + return tcp(ASIO_OS_DEF(AF_INET6)); + } + + /// Obtain an identifier for the type of the protocol. + int type() const + { + return ASIO_OS_DEF(SOCK_STREAM); + } + + /// Obtain an identifier for the protocol. + int protocol() const + { + return ASIO_OS_DEF(IPPROTO_TCP); + } + + /// Obtain an identifier for the protocol family. + int family() const + { + return family_; + } + + /// The TCP socket type. + typedef basic_stream_socket<tcp> socket; + + /// The TCP acceptor type. + typedef basic_socket_acceptor<tcp> acceptor; + + /// The TCP resolver type. + typedef basic_resolver<tcp> resolver; + + + /// Socket option for disabling the Nagle algorithm. + /** + * Implements the IPPROTO_TCP/TCP_NODELAY socket option. + * + * @par Examples + * Setting the option: + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::ip::tcp::no_delay option(true); + * socket.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::ip::tcp::no_delay option; + * socket.get_option(option); + * bool is_set = option.value(); + * @endcode + * + * @par Concepts: + * Socket_Option, Boolean_Socket_Option. + */ + typedef asio::detail::socket_option::boolean< + ASIO_OS_DEF(IPPROTO_TCP), ASIO_OS_DEF(TCP_NODELAY)> no_delay; + + /// Compare two protocols for equality. + friend bool operator==(const tcp& p1, const tcp& p2) + { + return p1.family_ == p2.family_; + } + + /// Compare two protocols for inequality. + friend bool operator!=(const tcp& p1, const tcp& p2) + { + return p1.family_ != p2.family_; + } + +private: + // Construct with a specific family. + explicit tcp(int protocol_family) + : family_(protocol_family) + { + } + + int family_; +}; + +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IP_TCP_HPP diff --git a/asio-1.10.6/include/asio/read.hpp b/asio-1.10.6/include/asio/read.hpp new file mode 100644 index 0000000..f6fd225 --- /dev/null +++ b/asio-1.10.6/include/asio/read.hpp @@ -0,0 +1,364 @@ +// +// read.hpp +// ~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_READ_HPP +#define ASIO_READ_HPP + + +#include "asio/detail/config.hpp" +#include <cstddef> +#include "asio/async_result.hpp" +#include "asio/basic_streambuf_fwd.hpp" +#include "asio/error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +/** + * @defgroup read asio::read + * + * @brief Attempt to read a certain amount of data from a stream before + * returning. + */ +/*@{*/ + +/// Attempt to read a certain amount of data from a stream before returning. +/** + * This function is used to read a certain number of bytes of data from a + * stream. The call will block until one of the following conditions is true: + * + * @li The supplied buffers are full. That is, the bytes transferred is equal to + * the sum of the buffer sizes. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param buffers One or more buffers into which the data will be read. The sum + * of the buffer sizes indicates the maximum number of bytes to read from the + * stream. + * + * @returns The number of bytes transferred. + * + * @throws asio::system_error Thrown on failure. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code asio::read(s, asio::buffer(data, size)); @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + * + * @note This overload is equivalent to calling: + * @code asio::read( + * s, buffers, + * asio::transfer_all()); @endcode + */ +template <typename SyncReadStream, typename MutableBufferSequence> +std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers); + +/// Attempt to read a certain amount of data from a stream before returning. +/** + * This function is used to read a certain number of bytes of data from a + * stream. The call will block until one of the following conditions is true: + * + * @li The supplied buffers are full. That is, the bytes transferred is equal to + * the sum of the buffer sizes. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param buffers One or more buffers into which the data will be read. The sum + * of the buffer sizes indicates the maximum number of bytes to read from the + * stream. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes transferred. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code asio::read(s, asio::buffer(data, size), ec); @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + * + * @note This overload is equivalent to calling: + * @code asio::read( + * s, buffers, + * asio::transfer_all(), ec); @endcode + */ +template <typename SyncReadStream, typename MutableBufferSequence> +std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, + asio::error_code& ec); + +/// Attempt to read a certain amount of data from a stream before returning. +/** + * This function is used to read a certain number of bytes of data from a + * stream. The call will block until one of the following conditions is true: + * + * @li The supplied buffers are full. That is, the bytes transferred is equal to + * the sum of the buffer sizes. + * + * @li The completion_condition function object returns 0. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param buffers One or more buffers into which the data will be read. The sum + * of the buffer sizes indicates the maximum number of bytes to read from the + * stream. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code std::size_t completion_condition( + * // Result of latest read_some operation. + * const asio::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of 0 indicates that the read operation is complete. A non-zero + * return value indicates the maximum number of bytes to be read on the next + * call to the stream's read_some function. + * + * @returns The number of bytes transferred. + * + * @throws asio::system_error Thrown on failure. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code asio::read(s, asio::buffer(data, size), + * asio::transfer_at_least(32)); @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ +template <typename SyncReadStream, typename MutableBufferSequence, + typename CompletionCondition> +std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, + CompletionCondition completion_condition); + +/// Attempt to read a certain amount of data from a stream before returning. +/** + * This function is used to read a certain number of bytes of data from a + * stream. The call will block until one of the following conditions is true: + * + * @li The supplied buffers are full. That is, the bytes transferred is equal to + * the sum of the buffer sizes. + * + * @li The completion_condition function object returns 0. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param buffers One or more buffers into which the data will be read. The sum + * of the buffer sizes indicates the maximum number of bytes to read from the + * stream. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code std::size_t completion_condition( + * // Result of latest read_some operation. + * const asio::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of 0 indicates that the read operation is complete. A non-zero + * return value indicates the maximum number of bytes to be read on the next + * call to the stream's read_some function. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. If an error occurs, returns the total + * number of bytes successfully transferred prior to the error. + */ +template <typename SyncReadStream, typename MutableBufferSequence, + typename CompletionCondition> +std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, + CompletionCondition completion_condition, asio::error_code& ec); + + +/*@}*/ +/** + * @defgroup async_read asio::async_read + * + * @brief Start an asynchronous operation to read a certain amount of data from + * a stream. + */ +/*@{*/ + +/// Start an asynchronous operation to read a certain amount of data from a +/// stream. +/** + * This function is used to asynchronously read a certain number of bytes of + * data from a stream. The function call always returns immediately. The + * asynchronous operation will continue until one of the following conditions is + * true: + * + * @li The supplied buffers are full. That is, the bytes transferred is equal to + * the sum of the buffer sizes. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * async_read_some function, and is known as a <em>composed operation</em>. The + * program must ensure that the stream performs no other read operations (such + * as async_read, the stream's async_read_some function, or any other composed + * operations that perform reads) until this operation completes. + * + * @param s The stream from which the data is to be read. The type must support + * the AsyncReadStream concept. + * + * @param buffers One or more buffers into which the data will be read. The sum + * of the buffer sizes indicates the maximum number of bytes to read from the + * stream. Although the buffers object may be copied as necessary, ownership of + * the underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * + * std::size_t bytes_transferred // Number of bytes copied into the + * // buffers. If an error occurred, + * // this will be the number of + * // bytes successfully transferred + * // prior to the error. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * asio::async_read(s, asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + * + * @note This overload is equivalent to calling: + * @code asio::async_read( + * s, buffers, + * asio::transfer_all(), + * handler); @endcode + */ +template <typename AsyncReadStream, typename MutableBufferSequence, + typename ReadHandler> +ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (asio::error_code, std::size_t)) +async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, + ASIO_MOVE_ARG(ReadHandler) handler); + +/// Start an asynchronous operation to read a certain amount of data from a +/// stream. +/** + * This function is used to asynchronously read a certain number of bytes of + * data from a stream. The function call always returns immediately. The + * asynchronous operation will continue until one of the following conditions is + * true: + * + * @li The supplied buffers are full. That is, the bytes transferred is equal to + * the sum of the buffer sizes. + * + * @li The completion_condition function object returns 0. + * + * @param s The stream from which the data is to be read. The type must support + * the AsyncReadStream concept. + * + * @param buffers One or more buffers into which the data will be read. The sum + * of the buffer sizes indicates the maximum number of bytes to read from the + * stream. Although the buffers object may be copied as necessary, ownership of + * the underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code std::size_t completion_condition( + * // Result of latest async_read_some operation. + * const asio::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of 0 indicates that the read operation is complete. A non-zero + * return value indicates the maximum number of bytes to be read on the next + * call to the stream's async_read_some function. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * + * std::size_t bytes_transferred // Number of bytes copied into the + * // buffers. If an error occurred, + * // this will be the number of + * // bytes successfully transferred + * // prior to the error. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code asio::async_read(s, + * asio::buffer(data, size), + * asio::transfer_at_least(32), + * handler); @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ +template <typename AsyncReadStream, typename MutableBufferSequence, + typename CompletionCondition, typename ReadHandler> +ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (asio::error_code, std::size_t)) +async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, + CompletionCondition completion_condition, + ASIO_MOVE_ARG(ReadHandler) handler); + + +/*@}*/ + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#include "asio/impl/read.hpp" + +#endif // ASIO_READ_HPP diff --git a/asio-1.10.6/include/asio/socket_acceptor_service.hpp b/asio-1.10.6/include/asio/socket_acceptor_service.hpp new file mode 100644 index 0000000..88b7220 --- /dev/null +++ b/asio-1.10.6/include/asio/socket_acceptor_service.hpp @@ -0,0 +1,265 @@ +// +// socket_acceptor_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_SOCKET_ACCEPTOR_SERVICE_HPP +#define ASIO_SOCKET_ACCEPTOR_SERVICE_HPP + + +#include "asio/detail/config.hpp" +#include "asio/basic_socket.hpp" +#include "asio/detail/type_traits.hpp" +#include "asio/error.hpp" +#include "asio/io_service.hpp" + +# include "asio/detail/reactive_socket_service.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +/// Default service implementation for a socket acceptor. +template <typename Protocol> +class socket_acceptor_service + : public asio::detail::service_base<socket_acceptor_service<Protocol> > +{ +public: + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename protocol_type::endpoint endpoint_type; + +private: + // The type of the platform-specific implementation. + typedef detail::reactive_socket_service<Protocol> service_impl_type; + +public: + /// The native type of the socket acceptor. + typedef typename service_impl_type::implementation_type implementation_type; + + /// (Deprecated: Use native_handle_type.) The native acceptor type. + typedef typename service_impl_type::native_handle_type native_type; + + /// The native acceptor type. + typedef typename service_impl_type::native_handle_type native_handle_type; + + /// Construct a new socket acceptor service for the specified io_service. + explicit socket_acceptor_service(asio::io_service& io_service) + : asio::detail::service_base< + socket_acceptor_service<Protocol> >(io_service), + service_impl_(io_service) + { + } + + /// Construct a new socket acceptor implementation. + void construct(implementation_type& impl) + { + service_impl_.construct(impl); + } + + /// Move-construct a new socket acceptor implementation. + void move_construct(implementation_type& impl, + implementation_type& other_impl) + { + service_impl_.move_construct(impl, other_impl); + } + + /// Move-assign from another socket acceptor implementation. + void move_assign(implementation_type& impl, + socket_acceptor_service& other_service, + implementation_type& other_impl) + { + service_impl_.move_assign(impl, other_service.service_impl_, other_impl); + } + + /// Move-construct a new socket acceptor implementation from another protocol + /// type. + template <typename Protocol1> + void converting_move_construct(implementation_type& impl, + typename socket_acceptor_service< + Protocol1>::implementation_type& other_impl, + typename enable_if<is_convertible< + Protocol1, Protocol>::value>::type* = 0) + { + service_impl_.template converting_move_construct<Protocol1>( + impl, other_impl); + } + + /// Destroy a socket acceptor implementation. + void destroy(implementation_type& impl) + { + service_impl_.destroy(impl); + } + + /// Open a new socket acceptor implementation. + asio::error_code open(implementation_type& impl, + const protocol_type& protocol, asio::error_code& ec) + { + return service_impl_.open(impl, protocol, ec); + } + + /// Assign an existing native acceptor to a socket acceptor. + asio::error_code assign(implementation_type& impl, + const protocol_type& protocol, const native_handle_type& native_acceptor, + asio::error_code& ec) + { + return service_impl_.assign(impl, protocol, native_acceptor, ec); + } + + /// Determine whether the acceptor is open. + bool is_open(const implementation_type& impl) const + { + return service_impl_.is_open(impl); + } + + /// Cancel all asynchronous operations associated with the acceptor. + asio::error_code cancel(implementation_type& impl, + asio::error_code& ec) + { + return service_impl_.cancel(impl, ec); + } + + /// Bind the socket acceptor to the specified local endpoint. + asio::error_code bind(implementation_type& impl, + const endpoint_type& endpoint, asio::error_code& ec) + { + return service_impl_.bind(impl, endpoint, ec); + } + + /// Place the socket acceptor into the state where it will listen for new + /// connections. + asio::error_code listen(implementation_type& impl, int backlog, + asio::error_code& ec) + { + return service_impl_.listen(impl, backlog, ec); + } + + /// Close a socket acceptor implementation. + asio::error_code close(implementation_type& impl, + asio::error_code& ec) + { + return service_impl_.close(impl, ec); + } + + /// (Deprecated: Use native_handle().) Get the native acceptor implementation. + native_type native(implementation_type& impl) + { + return service_impl_.native_handle(impl); + } + + /// Get the native acceptor implementation. + native_handle_type native_handle(implementation_type& impl) + { + return service_impl_.native_handle(impl); + } + + /// Set a socket option. + template <typename SettableSocketOption> + asio::error_code set_option(implementation_type& impl, + const SettableSocketOption& option, asio::error_code& ec) + { + return service_impl_.set_option(impl, option, ec); + } + + /// Get a socket option. + template <typename GettableSocketOption> + asio::error_code get_option(const implementation_type& impl, + GettableSocketOption& option, asio::error_code& ec) const + { + return service_impl_.get_option(impl, option, ec); + } + + /// Perform an IO control command on the socket. + template <typename IoControlCommand> + asio::error_code io_control(implementation_type& impl, + IoControlCommand& command, asio::error_code& ec) + { + return service_impl_.io_control(impl, command, ec); + } + + /// Gets the non-blocking mode of the acceptor. + bool non_blocking(const implementation_type& impl) const + { + return service_impl_.non_blocking(impl); + } + + /// Sets the non-blocking mode of the acceptor. + asio::error_code non_blocking(implementation_type& impl, + bool mode, asio::error_code& ec) + { + return service_impl_.non_blocking(impl, mode, ec); + } + + /// Gets the non-blocking mode of the native acceptor implementation. + bool native_non_blocking(const implementation_type& impl) const + { + return service_impl_.native_non_blocking(impl); + } + + /// Sets the non-blocking mode of the native acceptor implementation. + asio::error_code native_non_blocking(implementation_type& impl, + bool mode, asio::error_code& ec) + { + return service_impl_.native_non_blocking(impl, mode, ec); + } + + /// Get the local endpoint. + endpoint_type local_endpoint(const implementation_type& impl, + asio::error_code& ec) const + { + return service_impl_.local_endpoint(impl, ec); + } + + /// Accept a new connection. + template <typename Protocol1, typename SocketService> + asio::error_code accept(implementation_type& impl, + basic_socket<Protocol1, SocketService>& peer, + endpoint_type* peer_endpoint, asio::error_code& ec, + typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0) + { + return service_impl_.accept(impl, peer, peer_endpoint, ec); + } + + /// Start an asynchronous accept. + template <typename Protocol1, typename SocketService, typename AcceptHandler> + ASIO_INITFN_RESULT_TYPE(AcceptHandler, + void (asio::error_code)) + async_accept(implementation_type& impl, + basic_socket<Protocol1, SocketService>& peer, + endpoint_type* peer_endpoint, + ASIO_MOVE_ARG(AcceptHandler) handler, + typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0) + { + detail::async_result_init< + AcceptHandler, void (asio::error_code)> init( + ASIO_MOVE_CAST(AcceptHandler)(handler)); + + service_impl_.async_accept(impl, peer, peer_endpoint, init.handler); + + return init.result.get(); + } + +private: + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + service_impl_.shutdown_service(); + } + + // The platform-specific implementation. + service_impl_type service_impl_; +}; + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_SOCKET_ACCEPTOR_SERVICE_HPP diff --git a/asio-1.10.6/include/asio/socket_base.hpp b/asio-1.10.6/include/asio/socket_base.hpp new file mode 100644 index 0000000..3dc6ecd --- /dev/null +++ b/asio-1.10.6/include/asio/socket_base.hpp @@ -0,0 +1,436 @@ +// +// socket_base.hpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_SOCKET_BASE_HPP +#define ASIO_SOCKET_BASE_HPP + + +#include "asio/detail/config.hpp" +#include "asio/detail/io_control.hpp" +#include "asio/detail/socket_option.hpp" +#include "asio/detail/socket_types.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +/// The socket_base class is used as a base for the basic_stream_socket and +/// basic_datagram_socket class templates so that we have a common place to +/// define the shutdown_type and enum. +class socket_base +{ +public: + /// Different ways a socket may be shutdown. + enum shutdown_type + { + shutdown_receive = ASIO_OS_DEF(SHUT_RD), + shutdown_send = ASIO_OS_DEF(SHUT_WR), + shutdown_both = ASIO_OS_DEF(SHUT_RDWR) + }; + + /// Bitmask type for flags that can be passed to send and receive operations. + typedef int message_flags; + + ASIO_STATIC_CONSTANT(int, + message_peek = ASIO_OS_DEF(MSG_PEEK)); + ASIO_STATIC_CONSTANT(int, + message_out_of_band = ASIO_OS_DEF(MSG_OOB)); + ASIO_STATIC_CONSTANT(int, + message_do_not_route = ASIO_OS_DEF(MSG_DONTROUTE)); + ASIO_STATIC_CONSTANT(int, + message_end_of_record = ASIO_OS_DEF(MSG_EOR)); + + /// Socket option to permit sending of broadcast messages. + /** + * Implements the SOL_SOCKET/SO_BROADCAST socket option. + * + * @par Examples + * Setting the option: + * @code + * asio::ip::udp::socket socket(io_service); + * ... + * asio::socket_base::broadcast option(true); + * socket.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * asio::ip::udp::socket socket(io_service); + * ... + * asio::socket_base::broadcast option; + * socket.get_option(option); + * bool is_set = option.value(); + * @endcode + * + * @par Concepts: + * Socket_Option, Boolean_Socket_Option. + */ + typedef asio::detail::socket_option::boolean< + ASIO_OS_DEF(SOL_SOCKET), ASIO_OS_DEF(SO_BROADCAST)> + broadcast; + + /// Socket option to enable socket-level debugging. + /** + * Implements the SOL_SOCKET/SO_DEBUG socket option. + * + * @par Examples + * Setting the option: + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::socket_base::debug option(true); + * socket.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::socket_base::debug option; + * socket.get_option(option); + * bool is_set = option.value(); + * @endcode + * + * @par Concepts: + * Socket_Option, Boolean_Socket_Option. + */ + typedef asio::detail::socket_option::boolean< + ASIO_OS_DEF(SOL_SOCKET), ASIO_OS_DEF(SO_DEBUG)> debug; + + /// Socket option to prevent routing, use local interfaces only. + /** + * Implements the SOL_SOCKET/SO_DONTROUTE socket option. + * + * @par Examples + * Setting the option: + * @code + * asio::ip::udp::socket socket(io_service); + * ... + * asio::socket_base::do_not_route option(true); + * socket.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * asio::ip::udp::socket socket(io_service); + * ... + * asio::socket_base::do_not_route option; + * socket.get_option(option); + * bool is_set = option.value(); + * @endcode + * + * @par Concepts: + * Socket_Option, Boolean_Socket_Option. + */ + typedef asio::detail::socket_option::boolean< + ASIO_OS_DEF(SOL_SOCKET), ASIO_OS_DEF(SO_DONTROUTE)> + do_not_route; + + /// Socket option to send keep-alives. + /** + * Implements the SOL_SOCKET/SO_KEEPALIVE socket option. + * + * @par Examples + * Setting the option: + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::socket_base::keep_alive option(true); + * socket.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::socket_base::keep_alive option; + * socket.get_option(option); + * bool is_set = option.value(); + * @endcode + * + * @par Concepts: + * Socket_Option, Boolean_Socket_Option. + */ + typedef asio::detail::socket_option::boolean< + ASIO_OS_DEF(SOL_SOCKET), ASIO_OS_DEF(SO_KEEPALIVE)> keep_alive; + + /// Socket option for the send buffer size of a socket. + /** + * Implements the SOL_SOCKET/SO_SNDBUF socket option. + * + * @par Examples + * Setting the option: + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::socket_base::send_buffer_size option(8192); + * socket.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::socket_base::send_buffer_size option; + * socket.get_option(option); + * int size = option.value(); + * @endcode + * + * @par Concepts: + * Socket_Option, Integer_Socket_Option. + */ + typedef asio::detail::socket_option::integer< + ASIO_OS_DEF(SOL_SOCKET), ASIO_OS_DEF(SO_SNDBUF)> + send_buffer_size; + + /// Socket option for the send low watermark. + /** + * Implements the SOL_SOCKET/SO_SNDLOWAT socket option. + * + * @par Examples + * Setting the option: + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::socket_base::send_low_watermark option(1024); + * socket.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::socket_base::send_low_watermark option; + * socket.get_option(option); + * int size = option.value(); + * @endcode + * + * @par Concepts: + * Socket_Option, Integer_Socket_Option. + */ + typedef asio::detail::socket_option::integer< + ASIO_OS_DEF(SOL_SOCKET), ASIO_OS_DEF(SO_SNDLOWAT)> + send_low_watermark; + + /// Socket option for the receive buffer size of a socket. + /** + * Implements the SOL_SOCKET/SO_RCVBUF socket option. + * + * @par Examples + * Setting the option: + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::socket_base::receive_buffer_size option(8192); + * socket.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::socket_base::receive_buffer_size option; + * socket.get_option(option); + * int size = option.value(); + * @endcode + * + * @par Concepts: + * Socket_Option, Integer_Socket_Option. + */ + typedef asio::detail::socket_option::integer< + ASIO_OS_DEF(SOL_SOCKET), ASIO_OS_DEF(SO_RCVBUF)> + receive_buffer_size; + + /// Socket option for the receive low watermark. + /** + * Implements the SOL_SOCKET/SO_RCVLOWAT socket option. + * + * @par Examples + * Setting the option: + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::socket_base::receive_low_watermark option(1024); + * socket.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::socket_base::receive_low_watermark option; + * socket.get_option(option); + * int size = option.value(); + * @endcode + * + * @par Concepts: + * Socket_Option, Integer_Socket_Option. + */ + typedef asio::detail::socket_option::integer< + ASIO_OS_DEF(SOL_SOCKET), ASIO_OS_DEF(SO_RCVLOWAT)> + receive_low_watermark; + + /// Socket option to allow the socket to be bound to an address that is + /// already in use. + /** + * Implements the SOL_SOCKET/SO_REUSEADDR socket option. + * + * @par Examples + * Setting the option: + * @code + * asio::ip::tcp::acceptor acceptor(io_service); + * ... + * asio::socket_base::reuse_address option(true); + * acceptor.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * asio::ip::tcp::acceptor acceptor(io_service); + * ... + * asio::socket_base::reuse_address option; + * acceptor.get_option(option); + * bool is_set = option.value(); + * @endcode + * + * @par Concepts: + * Socket_Option, Boolean_Socket_Option. + */ + typedef asio::detail::socket_option::boolean< + ASIO_OS_DEF(SOL_SOCKET), ASIO_OS_DEF(SO_REUSEADDR)> + reuse_address; + + /// Socket option to specify whether the socket lingers on close if unsent + /// data is present. + /** + * Implements the SOL_SOCKET/SO_LINGER socket option. + * + * @par Examples + * Setting the option: + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::socket_base::linger option(true, 30); + * socket.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::socket_base::linger option; + * socket.get_option(option); + * bool is_set = option.enabled(); + * unsigned short timeout = option.timeout(); + * @endcode + * + * @par Concepts: + * Socket_Option, Linger_Socket_Option. + */ + typedef asio::detail::socket_option::linger< + ASIO_OS_DEF(SOL_SOCKET), ASIO_OS_DEF(SO_LINGER)> + linger; + + /// Socket option to report aborted connections on accept. + /** + * Implements a custom socket option that determines whether or not an accept + * operation is permitted to fail with asio::error::connection_aborted. + * By default the option is false. + * + * @par Examples + * Setting the option: + * @code + * asio::ip::tcp::acceptor acceptor(io_service); + * ... + * asio::socket_base::enable_connection_aborted option(true); + * acceptor.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * asio::ip::tcp::acceptor acceptor(io_service); + * ... + * asio::socket_base::enable_connection_aborted option; + * acceptor.get_option(option); + * bool is_set = option.value(); + * @endcode + * + * @par Concepts: + * Socket_Option, Boolean_Socket_Option. + */ + typedef asio::detail::socket_option::boolean< + asio::detail::custom_socket_option_level, + asio::detail::enable_connection_aborted_option> + enable_connection_aborted; + + /// (Deprecated: Use non_blocking().) IO control command to + /// set the blocking mode of the socket. + /** + * Implements the FIONBIO IO control command. + * + * @par Example + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::socket_base::non_blocking_io command(true); + * socket.io_control(command); + * @endcode + * + * @par Concepts: + * IO_Control_Command, Boolean_IO_Control_Command. + */ + typedef asio::detail::io_control::non_blocking_io non_blocking_io; + + /// IO control command to get the amount of data that can be read without + /// blocking. + /** + * Implements the FIONREAD IO control command. + * + * @par Example + * @code + * asio::ip::tcp::socket socket(io_service); + * ... + * asio::socket_base::bytes_readable command(true); + * socket.io_control(command); + * std::size_t bytes_readable = command.get(); + * @endcode + * + * @par Concepts: + * IO_Control_Command, Size_IO_Control_Command. + */ + typedef asio::detail::io_control::bytes_readable bytes_readable; + + /// The maximum length of the queue of pending incoming connections. + ASIO_STATIC_CONSTANT(int, max_connections + = ASIO_OS_DEF(SOMAXCONN)); + +protected: + /// Protected destructor to prevent deletion through this type. + ~socket_base() + { + } +}; + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_SOCKET_BASE_HPP diff --git a/asio-1.10.6/include/asio/stream_socket_service.hpp b/asio-1.10.6/include/asio/stream_socket_service.hpp new file mode 100644 index 0000000..3710449 --- /dev/null +++ b/asio-1.10.6/include/asio/stream_socket_service.hpp @@ -0,0 +1,339 @@ +// +// stream_socket_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_STREAM_SOCKET_SERVICE_HPP +#define ASIO_STREAM_SOCKET_SERVICE_HPP + + +#include "asio/detail/config.hpp" +#include <cstddef> +#include "asio/async_result.hpp" +#include "asio/detail/type_traits.hpp" +#include "asio/error.hpp" +#include "asio/io_service.hpp" + +# include "asio/detail/reactive_socket_service.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +/// Default service implementation for a stream socket. +template <typename Protocol> +class stream_socket_service + : public asio::detail::service_base<stream_socket_service<Protocol> > +{ +public: + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + +private: + // The type of the platform-specific implementation. + typedef detail::reactive_socket_service<Protocol> service_impl_type; + +public: + /// The type of a stream socket implementation. + typedef typename service_impl_type::implementation_type implementation_type; + + /// (Deprecated: Use native_handle_type.) The native socket type. + typedef typename service_impl_type::native_handle_type native_type; + + /// The native socket type. + typedef typename service_impl_type::native_handle_type native_handle_type; + + /// Construct a new stream socket service for the specified io_service. + explicit stream_socket_service(asio::io_service& io_service) + : asio::detail::service_base< + stream_socket_service<Protocol> >(io_service), + service_impl_(io_service) + { + } + + /// Construct a new stream socket implementation. + void construct(implementation_type& impl) + { + service_impl_.construct(impl); + } + + /// Move-construct a new stream socket implementation. + void move_construct(implementation_type& impl, + implementation_type& other_impl) + { + service_impl_.move_construct(impl, other_impl); + } + + /// Move-assign from another stream socket implementation. + void move_assign(implementation_type& impl, + stream_socket_service& other_service, + implementation_type& other_impl) + { + service_impl_.move_assign(impl, other_service.service_impl_, other_impl); + } + + /// Move-construct a new stream socket implementation from another protocol + /// type. + template <typename Protocol1> + void converting_move_construct(implementation_type& impl, + typename stream_socket_service< + Protocol1>::implementation_type& other_impl, + typename enable_if<is_convertible< + Protocol1, Protocol>::value>::type* = 0) + { + service_impl_.template converting_move_construct<Protocol1>( + impl, other_impl); + } + + /// Destroy a stream socket implementation. + void destroy(implementation_type& impl) + { + service_impl_.destroy(impl); + } + + /// Open a stream socket. + asio::error_code open(implementation_type& impl, + const protocol_type& protocol, asio::error_code& ec) + { + if (protocol.type() == ASIO_OS_DEF(SOCK_STREAM)) + service_impl_.open(impl, protocol, ec); + else + ec = asio::error::invalid_argument; + return ec; + } + + /// Assign an existing native socket to a stream socket. + asio::error_code assign(implementation_type& impl, + const protocol_type& protocol, const native_handle_type& native_socket, + asio::error_code& ec) + { + return service_impl_.assign(impl, protocol, native_socket, ec); + } + + /// Determine whether the socket is open. + bool is_open(const implementation_type& impl) const + { + return service_impl_.is_open(impl); + } + + /// Close a stream socket implementation. + asio::error_code close(implementation_type& impl, + asio::error_code& ec) + { + return service_impl_.close(impl, ec); + } + + /// (Deprecated: Use native_handle().) Get the native socket implementation. + native_type native(implementation_type& impl) + { + return service_impl_.native_handle(impl); + } + + /// Get the native socket implementation. + native_handle_type native_handle(implementation_type& impl) + { + return service_impl_.native_handle(impl); + } + + /// Cancel all asynchronous operations associated with the socket. + asio::error_code cancel(implementation_type& impl, + asio::error_code& ec) + { + return service_impl_.cancel(impl, ec); + } + + /// Determine whether the socket is at the out-of-band data mark. + bool at_mark(const implementation_type& impl, + asio::error_code& ec) const + { + return service_impl_.at_mark(impl, ec); + } + + /// Determine the number of bytes available for reading. + std::size_t available(const implementation_type& impl, + asio::error_code& ec) const + { + return service_impl_.available(impl, ec); + } + + /// Bind the stream socket to the specified local endpoint. + asio::error_code bind(implementation_type& impl, + const endpoint_type& endpoint, asio::error_code& ec) + { + return service_impl_.bind(impl, endpoint, ec); + } + + /// Connect the stream socket to the specified endpoint. + asio::error_code connect(implementation_type& impl, + const endpoint_type& peer_endpoint, asio::error_code& ec) + { + return service_impl_.connect(impl, peer_endpoint, ec); + } + + /// Start an asynchronous connect. + template <typename ConnectHandler> + ASIO_INITFN_RESULT_TYPE(ConnectHandler, + void (asio::error_code)) + async_connect(implementation_type& impl, + const endpoint_type& peer_endpoint, + ASIO_MOVE_ARG(ConnectHandler) handler) + { + detail::async_result_init< + ConnectHandler, void (asio::error_code)> init( + ASIO_MOVE_CAST(ConnectHandler)(handler)); + + service_impl_.async_connect(impl, peer_endpoint, init.handler); + + return init.result.get(); + } + + /// Set a socket option. + template <typename SettableSocketOption> + asio::error_code set_option(implementation_type& impl, + const SettableSocketOption& option, asio::error_code& ec) + { + return service_impl_.set_option(impl, option, ec); + } + + /// Get a socket option. + template <typename GettableSocketOption> + asio::error_code get_option(const implementation_type& impl, + GettableSocketOption& option, asio::error_code& ec) const + { + return service_impl_.get_option(impl, option, ec); + } + + /// Perform an IO control command on the socket. + template <typename IoControlCommand> + asio::error_code io_control(implementation_type& impl, + IoControlCommand& command, asio::error_code& ec) + { + return service_impl_.io_control(impl, command, ec); + } + + /// Gets the non-blocking mode of the socket. + bool non_blocking(const implementation_type& impl) const + { + return service_impl_.non_blocking(impl); + } + + /// Sets the non-blocking mode of the socket. + asio::error_code non_blocking(implementation_type& impl, + bool mode, asio::error_code& ec) + { + return service_impl_.non_blocking(impl, mode, ec); + } + + /// Gets the non-blocking mode of the native socket implementation. + bool native_non_blocking(const implementation_type& impl) const + { + return service_impl_.native_non_blocking(impl); + } + + /// Sets the non-blocking mode of the native socket implementation. + asio::error_code native_non_blocking(implementation_type& impl, + bool mode, asio::error_code& ec) + { + return service_impl_.native_non_blocking(impl, mode, ec); + } + + /// Get the local endpoint. + endpoint_type local_endpoint(const implementation_type& impl, + asio::error_code& ec) const + { + return service_impl_.local_endpoint(impl, ec); + } + + /// Get the remote endpoint. + endpoint_type remote_endpoint(const implementation_type& impl, + asio::error_code& ec) const + { + return service_impl_.remote_endpoint(impl, ec); + } + + /// Disable sends or receives on the socket. + asio::error_code shutdown(implementation_type& impl, + socket_base::shutdown_type what, asio::error_code& ec) + { + return service_impl_.shutdown(impl, what, ec); + } + + /// Send the given data to the peer. + template <typename ConstBufferSequence> + std::size_t send(implementation_type& impl, + const ConstBufferSequence& buffers, + socket_base::message_flags flags, asio::error_code& ec) + { + return service_impl_.send(impl, buffers, flags, ec); + } + + /// Start an asynchronous send. + template <typename ConstBufferSequence, typename WriteHandler> + ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (asio::error_code, std::size_t)) + async_send(implementation_type& impl, + const ConstBufferSequence& buffers, + socket_base::message_flags flags, + ASIO_MOVE_ARG(WriteHandler) handler) + { + detail::async_result_init< + WriteHandler, void (asio::error_code, std::size_t)> init( + ASIO_MOVE_CAST(WriteHandler)(handler)); + + service_impl_.async_send(impl, buffers, flags, init.handler); + + return init.result.get(); + } + + /// Receive some data from the peer. + template <typename MutableBufferSequence> + std::size_t receive(implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, asio::error_code& ec) + { + return service_impl_.receive(impl, buffers, flags, ec); + } + + /// Start an asynchronous receive. + template <typename MutableBufferSequence, typename ReadHandler> + ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (asio::error_code, std::size_t)) + async_receive(implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, + ASIO_MOVE_ARG(ReadHandler) handler) + { + detail::async_result_init< + ReadHandler, void (asio::error_code, std::size_t)> init( + ASIO_MOVE_CAST(ReadHandler)(handler)); + + service_impl_.async_receive(impl, buffers, flags, init.handler); + + return init.result.get(); + } + +private: + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + service_impl_.shutdown_service(); + } + + // The platform-specific implementation. + service_impl_type service_impl_; +}; + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_STREAM_SOCKET_SERVICE_HPP diff --git a/asio-1.10.6/include/asio/system_error.hpp b/asio-1.10.6/include/asio/system_error.hpp new file mode 100644 index 0000000..037f8cd --- /dev/null +++ b/asio-1.10.6/include/asio/system_error.hpp @@ -0,0 +1,31 @@ +// +// system_error.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_SYSTEM_ERROR_HPP +#define ASIO_SYSTEM_ERROR_HPP + + +#include "asio/detail/config.hpp" + +# include <system_error> + +#include "asio/detail/push_options.hpp" + +namespace asio { + + +typedef std::system_error system_error; + + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_SYSTEM_ERROR_HPP diff --git a/asio-1.10.6/include/asio/write.hpp b/asio-1.10.6/include/asio/write.hpp new file mode 100644 index 0000000..fc29f46 --- /dev/null +++ b/asio-1.10.6/include/asio/write.hpp @@ -0,0 +1,359 @@ +// +// write.hpp +// ~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_WRITE_HPP +#define ASIO_WRITE_HPP + + +#include "asio/detail/config.hpp" +#include <cstddef> +#include "asio/async_result.hpp" +#include "asio/basic_streambuf_fwd.hpp" +#include "asio/error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +/** + * @defgroup write asio::write + * + * @brief Write a certain amount of data to a stream before returning. + */ +/*@{*/ + +/// Write all of the supplied data to a stream before returning. +/** + * This function is used to write a certain number of bytes of data to a stream. + * The call will block until one of the following conditions is true: + * + * @li All of the data in the supplied buffers has been written. That is, the + * bytes transferred is equal to the sum of the buffer sizes. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * write_some function. + * + * @param s The stream to which the data is to be written. The type must support + * the SyncWriteStream concept. + * + * @param buffers One or more buffers containing the data to be written. The sum + * of the buffer sizes indicates the maximum number of bytes to write to the + * stream. + * + * @returns The number of bytes transferred. + * + * @throws asio::system_error Thrown on failure. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code asio::write(s, asio::buffer(data, size)); @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + * + * @note This overload is equivalent to calling: + * @code asio::write( + * s, buffers, + * asio::transfer_all()); @endcode + */ +template <typename SyncWriteStream, typename ConstBufferSequence> +std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers); + +/// Write all of the supplied data to a stream before returning. +/** + * This function is used to write a certain number of bytes of data to a stream. + * The call will block until one of the following conditions is true: + * + * @li All of the data in the supplied buffers has been written. That is, the + * bytes transferred is equal to the sum of the buffer sizes. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * write_some function. + * + * @param s The stream to which the data is to be written. The type must support + * the SyncWriteStream concept. + * + * @param buffers One or more buffers containing the data to be written. The sum + * of the buffer sizes indicates the maximum number of bytes to write to the + * stream. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes transferred. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code asio::write(s, asio::buffer(data, size), ec); @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + * + * @note This overload is equivalent to calling: + * @code asio::write( + * s, buffers, + * asio::transfer_all(), ec); @endcode + */ +template <typename SyncWriteStream, typename ConstBufferSequence> +std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, + asio::error_code& ec); + +/// Write a certain amount of data to a stream before returning. +/** + * This function is used to write a certain number of bytes of data to a stream. + * The call will block until one of the following conditions is true: + * + * @li All of the data in the supplied buffers has been written. That is, the + * bytes transferred is equal to the sum of the buffer sizes. + * + * @li The completion_condition function object returns 0. + * + * This operation is implemented in terms of zero or more calls to the stream's + * write_some function. + * + * @param s The stream to which the data is to be written. The type must support + * the SyncWriteStream concept. + * + * @param buffers One or more buffers containing the data to be written. The sum + * of the buffer sizes indicates the maximum number of bytes to write to the + * stream. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code std::size_t completion_condition( + * // Result of latest write_some operation. + * const asio::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of 0 indicates that the write operation is complete. A + * non-zero return value indicates the maximum number of bytes to be written on + * the next call to the stream's write_some function. + * + * @returns The number of bytes transferred. + * + * @throws asio::system_error Thrown on failure. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code asio::write(s, asio::buffer(data, size), + * asio::transfer_at_least(32)); @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ +template <typename SyncWriteStream, typename ConstBufferSequence, + typename CompletionCondition> +std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, + CompletionCondition completion_condition); + +/// Write a certain amount of data to a stream before returning. +/** + * This function is used to write a certain number of bytes of data to a stream. + * The call will block until one of the following conditions is true: + * + * @li All of the data in the supplied buffers has been written. That is, the + * bytes transferred is equal to the sum of the buffer sizes. + * + * @li The completion_condition function object returns 0. + * + * This operation is implemented in terms of zero or more calls to the stream's + * write_some function. + * + * @param s The stream to which the data is to be written. The type must support + * the SyncWriteStream concept. + * + * @param buffers One or more buffers containing the data to be written. The sum + * of the buffer sizes indicates the maximum number of bytes to write to the + * stream. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code std::size_t completion_condition( + * // Result of latest write_some operation. + * const asio::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of 0 indicates that the write operation is complete. A + * non-zero return value indicates the maximum number of bytes to be written on + * the next call to the stream's write_some function. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. If an error occurs, returns the total + * number of bytes successfully transferred prior to the error. + */ +template <typename SyncWriteStream, typename ConstBufferSequence, + typename CompletionCondition> +std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, + CompletionCondition completion_condition, asio::error_code& ec); + + +/*@}*/ +/** + * @defgroup async_write asio::async_write + * + * @brief Start an asynchronous operation to write a certain amount of data to a + * stream. + */ +/*@{*/ + +/// Start an asynchronous operation to write all of the supplied data to a +/// stream. +/** + * This function is used to asynchronously write a certain number of bytes of + * data to a stream. The function call always returns immediately. The + * asynchronous operation will continue until one of the following conditions + * is true: + * + * @li All of the data in the supplied buffers has been written. That is, the + * bytes transferred is equal to the sum of the buffer sizes. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * async_write_some function, and is known as a <em>composed operation</em>. The + * program must ensure that the stream performs no other write operations (such + * as async_write, the stream's async_write_some function, or any other composed + * operations that perform writes) until this operation completes. + * + * @param s The stream to which the data is to be written. The type must support + * the AsyncWriteStream concept. + * + * @param buffers One or more buffers containing the data to be written. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * + * std::size_t bytes_transferred // Number of bytes written from the + * // buffers. If an error occurred, + * // this will be less than the sum + * // of the buffer sizes. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * asio::async_write(s, asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ +template <typename AsyncWriteStream, typename ConstBufferSequence, + typename WriteHandler> +ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (asio::error_code, std::size_t)) +async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, + ASIO_MOVE_ARG(WriteHandler) handler); + +/// Start an asynchronous operation to write a certain amount of data to a +/// stream. +/** + * This function is used to asynchronously write a certain number of bytes of + * data to a stream. The function call always returns immediately. The + * asynchronous operation will continue until one of the following conditions + * is true: + * + * @li All of the data in the supplied buffers has been written. That is, the + * bytes transferred is equal to the sum of the buffer sizes. + * + * @li The completion_condition function object returns 0. + * + * This operation is implemented in terms of zero or more calls to the stream's + * async_write_some function, and is known as a <em>composed operation</em>. The + * program must ensure that the stream performs no other write operations (such + * as async_write, the stream's async_write_some function, or any other composed + * operations that perform writes) until this operation completes. + * + * @param s The stream to which the data is to be written. The type must support + * the AsyncWriteStream concept. + * + * @param buffers One or more buffers containing the data to be written. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code std::size_t completion_condition( + * // Result of latest async_write_some operation. + * const asio::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of 0 indicates that the write operation is complete. A + * non-zero return value indicates the maximum number of bytes to be written on + * the next call to the stream's async_write_some function. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * + * std::size_t bytes_transferred // Number of bytes written from the + * // buffers. If an error occurred, + * // this will be less than the sum + * // of the buffer sizes. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code asio::async_write(s, + * asio::buffer(data, size), + * asio::transfer_at_least(32), + * handler); @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ +template <typename AsyncWriteStream, typename ConstBufferSequence, + typename CompletionCondition, typename WriteHandler> +ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (asio::error_code, std::size_t)) +async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, + CompletionCondition completion_condition, + ASIO_MOVE_ARG(WriteHandler) handler); + + +/*@}*/ + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#include "asio/impl/write.hpp" + +#endif // ASIO_WRITE_HPP |
