diff --git a/asio/src/Makefile.am b/asio/src/Makefile.am index 062950c4..2fbbd9ba 100644 --- a/asio/src/Makefile.am +++ b/asio/src/Makefile.am @@ -11,8 +11,6 @@ ___lib_libasio_a_SOURCES = \ asio/demuxer.cpp \ asio/demuxer_service.cpp \ asio/demuxer_task.cpp \ - asio/dgram_socket.cpp \ - asio/dgram_socket_service.cpp \ asio/generic_address.cpp \ asio/inet_address_v4.cpp \ asio/service.cpp \ @@ -20,17 +18,13 @@ ___lib_libasio_a_SOURCES = \ asio/service_provider_factory.cpp \ asio/service_unavailable.cpp \ asio/socket_acceptor.cpp \ - asio/socket_acceptor_service.cpp \ asio/socket_address.cpp \ asio/socket_connector.cpp \ - asio/socket_connector_service.cpp \ asio/socket_error.cpp \ asio/stream_socket.cpp \ - asio/stream_socket_service.cpp \ - asio/timer_queue.cpp \ - asio/timer_queue_service.cpp \ asio/detail/default_service_provider_factory.cpp \ asio/detail/demuxer_thread_pool.cpp \ + asio/detail/dgram_socket_service.cpp \ asio/detail/selector.cpp \ asio/detail/select_interrupter.cpp \ asio/detail/select_op.cpp \ @@ -38,12 +32,18 @@ ___lib_libasio_a_SOURCES = \ asio/detail/select_provider.cpp \ asio/detail/service_registry.cpp \ asio/detail/shared_thread_demuxer_provider.cpp \ + asio/detail/socket_acceptor_service.cpp \ asio/detail/socket_connector_impl.cpp \ + asio/detail/socket_connector_service.cpp \ + asio/detail/stream_socket_service.cpp \ asio/detail/timer_queue_provider.cpp \ + asio/detail/timer_queue_service.cpp \ asio/detail/win_iocp_provider.cpp nobase_include_HEADERS = \ asio.hpp \ + asio/basic_dgram_socket.hpp \ + asio/basic_timer_queue.hpp \ asio/buffered_recv_stream.hpp \ asio/buffered_send_stream.hpp \ asio/buffered_stream.hpp \ @@ -54,7 +54,6 @@ nobase_include_HEADERS = \ asio/demuxer_service.hpp \ asio/demuxer_task.hpp \ asio/dgram_socket.hpp \ - asio/dgram_socket_service.hpp \ asio/generic_address.hpp \ asio/inet_address_v4.hpp \ asio/service.hpp \ @@ -63,18 +62,19 @@ nobase_include_HEADERS = \ asio/service_type_id.hpp \ asio/service_unavailable.hpp \ asio/socket_acceptor.hpp \ - asio/socket_acceptor_service.hpp \ asio/socket_address.hpp \ asio/socket_connector.hpp \ - asio/socket_connector_service.hpp \ asio/socket_error.hpp \ asio/stream_socket.hpp \ - asio/stream_socket_service.hpp \ asio/timer_queue.hpp \ - asio/timer_queue_service.hpp \ + asio/detail/dgram_socket_service.hpp \ asio/detail/pop_options.hpp \ asio/detail/push_options.hpp \ - asio/detail/socket_types.hpp + asio/detail/socket_acceptor_service.hpp \ + asio/detail/socket_connector_service.hpp \ + asio/detail/stream_socket_service.hpp \ + asio/detail/socket_types.hpp \ + asio/detail/timer_queue_service.hpp noinst_HEADERS = \ asio/detail/default_service_provider_factory.hpp \ diff --git a/asio/src/asio.hpp b/asio/src/asio.hpp index 7296b58d..ed409913 100644 --- a/asio/src/asio.hpp +++ b/asio/src/asio.hpp @@ -15,6 +15,8 @@ #ifndef ASIO_HPP #define ASIO_HPP +#include "asio/basic_dgram_socket.hpp" +#include "asio/basic_timer_queue.hpp" #include "asio/buffered_recv_stream.hpp" #include "asio/buffered_send_stream.hpp" #include "asio/buffered_stream.hpp" @@ -25,7 +27,6 @@ #include "asio/demuxer_service.hpp" #include "asio/demuxer_task.hpp" #include "asio/dgram_socket.hpp" -#include "asio/dgram_socket_service.hpp" #include "asio/generic_address.hpp" #include "asio/inet_address_v4.hpp" #include "asio/service.hpp" @@ -34,12 +35,9 @@ #include "asio/service_type_id.hpp" #include "asio/service_unavailable.hpp" #include "asio/socket_acceptor.hpp" -#include "asio/socket_acceptor_service.hpp" #include "asio/socket_address.hpp" #include "asio/socket_connector.hpp" -#include "asio/socket_connector_service.hpp" #include "asio/socket_error.hpp" #include "asio/timer_queue.hpp" -#include "asio/timer_queue_service.hpp" #endif // ASIO_HPP diff --git a/asio/src/asio/basic_dgram_socket.hpp b/asio/src/asio/basic_dgram_socket.hpp new file mode 100644 index 00000000..26d68644 --- /dev/null +++ b/asio/src/asio/basic_dgram_socket.hpp @@ -0,0 +1,145 @@ +// +// basic_dgram_socket.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003 Christopher M. Kohlhoff (chris@kohlhoff.com) +// +// Permission to use, copy, modify, distribute and sell this software and its +// documentation for any purpose is hereby granted without fee, provided that +// the above copyright notice appears in all copies and that both the copyright +// notice and this permission notice appear in supporting documentation. This +// software is provided "as is" without express or implied warranty, and with +// no claim as to its suitability for any purpose. +// + +#ifndef ASIO_BASIC_DGRAM_SOCKET_HPP +#define ASIO_BASIC_DGRAM_SOCKET_HPP + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/completion_context.hpp" +#include "asio/demuxer.hpp" + +namespace asio { + +class socket_address; +class socket_error; + +/// The basic_dgram_socket class template provides asynchronous and blocking +/// datagram-oriented socket functionality. Most applications will simply use +/// the dgram_socket typedef. +template +class basic_dgram_socket + : private boost::noncopyable +{ +public: + /// The native implementation type of the dgram socket. + typedef typename Service::impl_type impl_type; + + /// Construct a dgram_socket without opening it. The socket needs to be + /// opened before data can be sent or received on it. + explicit basic_dgram_socket(demuxer& d) + : service_(dynamic_cast(d.get_service(Service::id))) + { + service_.nullify(impl_); + } + + /// Construct a dgram_socket opened on the given address. + basic_dgram_socket(demuxer& d, const socket_address& address) + : service_(dynamic_cast(d.get_service(Service::id))) + { + service_.create(impl_, address); + } + + /// Destructor. + ~basic_dgram_socket() + { + service_.destroy(impl_); + } + + /// Open the socket on the given address. + void open(const socket_address& address) + { + service_.create(impl_, address); + } + + /// Close the socket. + void close() + { + service_.destroy(impl_); + } + + /// Get the underlying implementation in the native type. + impl_type impl() const + { + return impl_; + } + + /// Attach an existing implementation to the dgram socket. The dgram_socket + /// object takes ownership of the implementation. + void attach_impl(impl_type impl) + { + service_.attach(impl_, impl); + } + + /// Send a datagram to the specified address. Returns the number of bytes + /// sent. Throws a socket_error exception on failure. + size_t sendto(const void* data, size_t length, + const socket_address& destination) + { + return service_.sendto(impl_, data, length, destination); + } + + /// The handler when a sendto operation is completed. The first argument is + /// the error code, the second is the number of bytes sent. + typedef typename Service::sendto_handler sendto_handler; + + /// Start an asynchronous send. The data being sent must be valid for the + /// lifetime of the asynchronous operation. + void async_sendto(const void* data, size_t length, + const socket_address& destination, const sendto_handler& handler, + completion_context& context = completion_context::null()) + { + service_.async_sendto(impl_, data, length, destination, handler, context); + } + + /// Receive a datagram with the address of the sender. Returns the number of + /// bytes received. Throws a socket_error exception on failure. + size_t recvfrom(void* data, size_t max_length, + socket_address& sender_address) + { + return service_.recvfrom(impl_, data, max_length, sender_address); + } + + /// The handler when a recvfrom operation is completed. The first argument is + /// the error code, the second is the number of bytes received. + typedef typename Service::recvfrom_handler recvfrom_handler; + + /// Start an asynchronous receive. The buffer for the data being received and + /// the sender_address obejct must both be valid for the lifetime of the + /// asynchronous operation. + void async_recvfrom(void* data, size_t max_length, + socket_address& sender_address, const recvfrom_handler& handler, + completion_context& context = completion_context::null()) + { + service_.async_recvfrom(impl_, data, max_length, sender_address, handler, + context); + } + +private: + /// The backend service implementation. + Service& service_; + + /// The underlying native implementation. + impl_type impl_; +}; + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_BASIC_DGRAM_SOCKET_HPP diff --git a/asio/src/asio/basic_timer_queue.hpp b/asio/src/asio/basic_timer_queue.hpp new file mode 100644 index 00000000..5a9ad10c --- /dev/null +++ b/asio/src/asio/basic_timer_queue.hpp @@ -0,0 +1,82 @@ +// +// basic_timer_queue.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003 Christopher M. Kohlhoff (chris@kohlhoff.com) +// +// Permission to use, copy, modify, distribute and sell this software and its +// documentation for any purpose is hereby granted without fee, provided that +// the above copyright notice appears in all copies and that both the copyright +// notice and this permission notice appear in supporting documentation. This +// software is provided "as is" without express or implied warranty, and with +// no claim as to its suitability for any purpose. +// + +#ifndef ASIO_BASIC_TIMER_QUEUE_HPP +#define ASIO_BASIC_TIMER_QUEUE_HPP + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/completion_context.hpp" +#include "asio/demuxer.hpp" + +namespace asio { + +/// The basic_timer_queue class template provides asynchronous timer +/// functionality. Most applications will simply use the timer_queue typedef. +template +class basic_timer_queue + : private boost::noncopyable +{ +public: + /// Constructor. + explicit basic_timer_queue(demuxer& d) + : service_(dynamic_cast(d.get_service(Service::id))) + { + } + + /// The handler for when a timer expires. + typedef typename Service::timer_handler timer_handler; + + /// Schedule a timer to fire once at the given start_time. The id of the new + /// timer is returned so that it may be cancelled. + int schedule_timer(const boost::xtime& start_time, + const timer_handler& handler, + completion_context& context = completion_context::null()) + { + return service_.schedule_timer(this, start_time, handler, context); + } + + /// Schedule a timer to fire first after at the start time, and then every + /// interval until the timer is cancelled. The id of the new timer is + /// returned so that it may be cancelled. + int schedule_timer(const boost::xtime& start_time, + const boost::xtime& interval, const timer_handler& handler, + completion_context& context = completion_context::null()) + { + return service_.schedule_timer(this, start_time, interval, handler, + context); + } + + /// Cancel the timer with the given id. + void cancel_timer(int timer_id) + { + service_.cancel_timer(this, timer_id); + } + +private: + /// The backend service implementation. + Service& service_; +}; + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_BASIC_TIMER_QUEUE_HPP diff --git a/asio/src/asio/detail/dgram_socket_service.cpp b/asio/src/asio/detail/dgram_socket_service.cpp new file mode 100644 index 00000000..bf75a32b --- /dev/null +++ b/asio/src/asio/detail/dgram_socket_service.cpp @@ -0,0 +1,138 @@ +// +// dgram_socket_service.cpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003 Christopher M. Kohlhoff (chris@kohlhoff.com) +// +// Permission to use, copy, modify, distribute and sell this software and its +// documentation for any purpose is hereby granted without fee, provided that +// the above copyright notice appears in all copies and that both the copyright +// notice and this permission notice appear in supporting documentation. This +// software is provided "as is" without express or implied warranty, and with +// no claim as to its suitability for any purpose. +// + +#include "asio/detail/dgram_socket_service.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/socket_address.hpp" +#include "asio/socket_error.hpp" +#include "asio/detail/socket_holder.hpp" +#include "asio/detail/socket_ops.hpp" + +namespace asio { +namespace detail { + +const service_type_id dgram_socket_service::id; + +void +dgram_socket_service:: +nullify( + impl_type& impl) +{ + impl = invalid_socket; +} + +void +dgram_socket_service:: +create( + impl_type& impl, + const socket_address& address) +{ + socket_holder sock(socket_ops::socket(address.family(), SOCK_DGRAM, + IPPROTO_UDP)); + if (sock.get() == invalid_socket) + boost::throw_exception(socket_error(socket_ops::get_error())); + + int reuse = 1; + socket_ops::setsockopt(sock.get(), SOL_SOCKET, SO_REUSEADDR, &reuse, + sizeof(reuse)); + + if (socket_ops::bind(sock.get(), address.native_address(), + address.native_size()) == socket_error_retval) + boost::throw_exception(socket_error(socket_ops::get_error())); + + impl = sock.release(); +} + +void +attach( + impl_type& impl, + impl_type new_impl) +{ + impl = new_impl; +} + +void +dgram_socket_service:: +destroy( + impl_type& impl) +{ + do_dgram_socket_destroy(impl); +} + +size_t +dgram_socket_service:: +sendto( + impl_type& impl, + const void* data, + size_t length, + const socket_address& destination) +{ + int bytes_sent = socket_ops::sendto(impl, data, length, 0, + destination.native_address(), destination.native_size()); + if (bytes_sent < 0) + boost::throw_exception(socket_error(socket_ops::get_error())); + return bytes_sent; +} + +void +dgram_socket_service:: +async_sendto( + impl_type& impl, + const void* data, + size_t length, + const socket_address& destination, + const sendto_handler& handler, + completion_context& context) +{ + do_dgram_socket_async_sendto(impl, data, length, destination, handler, + context); +} + +size_t +dgram_socket_service:: +recvfrom( + impl_type& impl, + void* data, + size_t max_length, + socket_address& sender_address) +{ + socket_addr_len_type addr_len = sender_address.native_size(); + int bytes_recvd = socket_ops::recvfrom(impl, data, max_length, 0, + sender_address.native_address(), &addr_len); + if (bytes_recvd < 0) + boost::throw_exception(socket_error(socket_ops::get_error())); + sender_address.native_size(addr_len); + return bytes_recvd; +} + +void +dgram_socket_service:: +async_recvfrom( + impl_type& impl, + void* data, + size_t max_length, + socket_address& sender_address, + const recvfrom_handler& handler, + completion_context& context) +{ + do_dgram_socket_async_recvfrom(impl, data, max_length, sender_address, + handler, context); +} + +} // namespace detail +} // namespace asio diff --git a/asio/src/asio/detail/dgram_socket_service.hpp b/asio/src/asio/detail/dgram_socket_service.hpp new file mode 100644 index 00000000..1b8bc069 --- /dev/null +++ b/asio/src/asio/detail/dgram_socket_service.hpp @@ -0,0 +1,109 @@ +// +// dgram_socket_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003 Christopher M. Kohlhoff (chris@kohlhoff.com) +// +// Permission to use, copy, modify, distribute and sell this software and its +// documentation for any purpose is hereby granted without fee, provided that +// the above copyright notice appears in all copies and that both the copyright +// notice and this permission notice appear in supporting documentation. This +// software is provided "as is" without express or implied warranty, and with +// no claim as to its suitability for any purpose. +// + +#ifndef ASIO_DETAIL_DGRAM_SOCKET_SERVICE_HPP +#define ASIO_DETAIL_DGRAM_SOCKET_SERVICE_HPP + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/completion_context.hpp" +#include "asio/service.hpp" +#include "asio/service_type_id.hpp" +#include "asio/detail/socket_types.hpp" + +namespace asio { class socket_address; } +namespace asio { class socket_error; } + +namespace asio { +namespace detail { + +class dgram_socket_service + : public virtual service +{ +public: + // The service type id. + static const service_type_id id; + + /// The native type of the dgram socket. This type is dependent on the + /// underlying implementation of the socket layer. + typedef socket_type impl_type; + + // Initialise a dgram socket to a null implementation. + void nullify(impl_type& impl); + + // Create a new dgram socket implementation. + void create(impl_type& impl, const socket_address& address); + + // Attach an existing dgram socket implementation to the service. + void attach(impl_type& impl, impl_type new_impl); + + // Destroy a dgram socket implementation. + void destroy(impl_type& impl); + + /// Send a datagram to the specified address. Returns the number of bytes + /// sent. Throws a socket_error exception on failure. + size_t sendto(impl_type& impl, const void* data, size_t length, + const socket_address& destination); + + /// The handler when a sendto operation is completed. The first argument is + /// the error code, the second is the number of bytes sent. + typedef boost::function2 sendto_handler; + + // Start an asynchronous send. The data being sent must be valid for the + // lifetime of the asynchronous operation. + void async_sendto(impl_type& impl, const void* data, size_t length, + const socket_address& destination, const sendto_handler& handler, + completion_context& context); + + /// Receive a datagram with the address of the sender. Returns the number of + /// bytes received. Throws a socket_error exception on failure. + size_t recvfrom(impl_type& impl, void* data, size_t max_length, + socket_address& sender_address); + + /// The handler when a recvfrom operation is completed. The first argument is + /// the error code, the second is the number of bytes received. + typedef boost::function2 recvfrom_handler; + + // Start an asynchronous receive. The buffer for the data being received and + // the sender_address obejct must both be valid for the lifetime of the + // asynchronous operation. + void async_recvfrom(impl_type& impl, void* data, size_t max_length, + socket_address& sender_address, const recvfrom_handler& handler, + completion_context& context); + +private: + // Destroy a dgram socket implementation. + virtual void do_dgram_socket_destroy(impl_type& impl) = 0; + + // Start an asynchronous sendto. + virtual void do_dgram_socket_async_sendto(impl_type& impl, const void* data, + size_t length, const socket_address& destination, + const sendto_handler& handler, completion_context& context) = 0; + + // Start an asynchronous recvfrom. + virtual void do_dgram_socket_async_recvfrom(impl_type& impl, void* data, + size_t max_length, socket_address& sender_address, + const recvfrom_handler& handler, completion_context& context) = 0; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_DGRAM_SOCKET_SERVICE_HPP diff --git a/asio/src/asio/detail/select_provider.cpp b/asio/src/asio/detail/select_provider.cpp index 28d965ab..944725e7 100644 --- a/asio/src/asio/detail/select_provider.cpp +++ b/asio/src/asio/detail/select_provider.cpp @@ -57,19 +57,15 @@ do_get_service( void select_provider:: -register_dgram_socket( - dgram_socket&) +do_dgram_socket_destroy( + dgram_socket_service::impl_type& impl) { - // Registration is not required with the select_provider since each operation - // is handled individually. -} - -void -select_provider:: -deregister_dgram_socket( - dgram_socket& socket) -{ - selector_.close_descriptor(socket.native_handle()); + if (impl != invalid_socket) + { + selector_.close_descriptor(impl); + socket_ops::close(impl); + impl = invalid_socket; + } } namespace @@ -80,7 +76,7 @@ namespace const void* data_; size_t length_; generic_address destination_; - dgram_socket::sendto_handler handler_; + dgram_socket_service::sendto_handler handler_; completion_context* context_; sendto_op(int d) : select_op(d) {} @@ -104,7 +100,7 @@ namespace delete this; } - static void do_upcall(const dgram_socket::sendto_handler& handler, + static void do_upcall(const dgram_socket_service::sendto_handler& handler, const socket_error& error, size_t bytes_transferred) { handler(error, bytes_transferred); @@ -114,15 +110,15 @@ namespace void select_provider:: -async_dgram_socket_sendto( - dgram_socket& socket, +do_dgram_socket_async_sendto( + dgram_socket_service::impl_type& impl, const void* data, size_t length, const socket_address& destination, const sendto_handler& handler, completion_context& context) { - sendto_op* op = new sendto_op(socket.native_handle()); + sendto_op* op = new sendto_op(impl); op->demuxer_ = &demuxer_; op->data_ = data; op->length_ = length; @@ -143,7 +139,7 @@ namespace void* data_; size_t max_length_; socket_address* sender_address_; - dgram_socket::recvfrom_handler handler_; + dgram_socket_service::recvfrom_handler handler_; completion_context* context_; recvfrom_op(int d) : select_op(d) {} @@ -169,7 +165,8 @@ namespace delete this; } - static void do_upcall(const dgram_socket::recvfrom_handler& handler, + static void do_upcall( + const dgram_socket_service::recvfrom_handler& handler, const socket_error& error, size_t bytes_transferred) { handler(error, bytes_transferred); @@ -179,15 +176,15 @@ namespace void select_provider:: -async_dgram_socket_recvfrom( - dgram_socket& socket, +do_dgram_socket_async_recvfrom( + dgram_socket_service::impl_type& impl, void* data, size_t max_length, socket_address& sender_address, const recvfrom_handler& handler, completion_context& context) { - recvfrom_op* op = new recvfrom_op(socket.native_handle()); + recvfrom_op* op = new recvfrom_op(impl); op->demuxer_ = &demuxer_; op->data_ = data; op->max_length_ = max_length; @@ -265,7 +262,7 @@ async_socket_accept( const accept_handler& handler, completion_context& context) { - if (peer_socket.native_handle() != detail::invalid_socket) + if (peer_socket.native_handle() != invalid_socket) { socket_error error(socket_error::already_connected); demuxer_.operation_immediate( @@ -338,7 +335,7 @@ async_socket_accept( const accept_handler& handler, completion_context& context) { - if (peer_socket.native_handle() != detail::invalid_socket) + if (peer_socket.native_handle() != invalid_socket) { socket_error error(socket_error::already_connected); demuxer_.operation_immediate( @@ -483,7 +480,7 @@ async_socket_connect( const connect_handler& handler, completion_context& context) { - if (peer_socket.native_handle() != detail::invalid_socket) + if (peer_socket.native_handle() != invalid_socket) { socket_error error(socket_error::already_connected); demuxer_.operation_immediate( diff --git a/asio/src/asio/detail/select_provider.hpp b/asio/src/asio/detail/select_provider.hpp index 80d94b38..7aa6424e 100644 --- a/asio/src/asio/detail/select_provider.hpp +++ b/asio/src/asio/detail/select_provider.hpp @@ -17,12 +17,12 @@ #include "asio/detail/push_options.hpp" -#include "asio/dgram_socket_service.hpp" #include "asio/service_provider.hpp" -#include "asio/socket_acceptor_service.hpp" -#include "asio/socket_connector_service.hpp" -#include "asio/stream_socket_service.hpp" +#include "asio/detail/dgram_socket_service.hpp" #include "asio/detail/selector.hpp" +#include "asio/detail/socket_acceptor_service.hpp" +#include "asio/detail/socket_connector_service.hpp" +#include "asio/detail/stream_socket_service.hpp" namespace asio { namespace detail { @@ -44,26 +44,20 @@ public: // Return the service interface corresponding to the given type. virtual service* do_get_service(const service_type_id& service_type); - // Register a new dgram socket with the service. This should be called only - // after the socket has been opened. - virtual void register_dgram_socket(dgram_socket& socket); + // Destroy a dgram socket implementation. + virtual void do_dgram_socket_destroy(dgram_socket_service::impl_type& impl); - // Remove a dgram socket registration from the service. This should be - // called immediately before the socket is closed. - virtual void deregister_dgram_socket(dgram_socket& socket); + // Start an asynchronous sendto. + virtual void do_dgram_socket_async_sendto( + dgram_socket_service::impl_type& impl, const void* data, size_t length, + const socket_address& destination, const sendto_handler& handler, + completion_context& context); - // Start an asynchronous send. The data being sent must be valid for the - // lifetime of the asynchronous operation. - virtual void async_dgram_socket_sendto(dgram_socket& socket, - const void* data, size_t length, const socket_address& destination, - const sendto_handler& handler, completion_context& context); - - // Start an asynchronous receive. The buffer for the data being received and - // the sender_address obejct must both be valid for the lifetime of the - // asynchronous operation. - virtual void async_dgram_socket_recvfrom(dgram_socket& socket, void* data, - size_t max_length, socket_address& sender_address, - const recvfrom_handler& handler, completion_context& context); + // Start an asynchronous recvfrom. + virtual void do_dgram_socket_async_recvfrom( + dgram_socket_service::impl_type& impl, void* data, size_t max_length, + socket_address& sender_address, const recvfrom_handler& handler, + completion_context& context); // Register a new socket_acceptor with the service. This should be called // only after the socket acceptor has been opened. diff --git a/asio/src/asio/socket_acceptor_service.cpp b/asio/src/asio/detail/socket_acceptor_service.cpp similarity index 90% rename from asio/src/asio/socket_acceptor_service.cpp rename to asio/src/asio/detail/socket_acceptor_service.cpp index ee89399f..6acfed43 100644 --- a/asio/src/asio/socket_acceptor_service.cpp +++ b/asio/src/asio/detail/socket_acceptor_service.cpp @@ -12,9 +12,10 @@ // no claim as to its suitability for any purpose. // -#include "asio/socket_acceptor_service.hpp" +#include "asio/detail/socket_acceptor_service.hpp" namespace asio { +namespace detail { const service_type_id socket_acceptor_service::id; @@ -28,4 +29,5 @@ associate_accepted_stream_socket( acceptor.associate(peer_socket, handle); } +} // namespace detail } // namespace asio diff --git a/asio/src/asio/socket_acceptor_service.hpp b/asio/src/asio/detail/socket_acceptor_service.hpp similarity index 62% rename from asio/src/asio/socket_acceptor_service.hpp rename to asio/src/asio/detail/socket_acceptor_service.hpp index 5c5af79c..c36e9de2 100644 --- a/asio/src/asio/socket_acceptor_service.hpp +++ b/asio/src/asio/detail/socket_acceptor_service.hpp @@ -12,8 +12,8 @@ // no claim as to its suitability for any purpose. // -#ifndef ASIO_SOCKET_ACCEPTOR_SERVICE_HPP -#define ASIO_SOCKET_ACCEPTOR_SERVICE_HPP +#ifndef ASIO_DETAIL_SOCKET_ACCEPTOR_SERVICE_HPP +#define ASIO_DETAIL_SOCKET_ACCEPTOR_SERVICE_HPP #include "asio/detail/push_options.hpp" @@ -23,49 +23,48 @@ #include "asio/stream_socket.hpp" namespace asio { +namespace detail { -/// The socket_acceptor_service class is a base class for service -/// implementations that provide the functionality required by the -/// socket_acceptor class. class socket_acceptor_service : public virtual service { public: typedef socket_acceptor::accept_handler accept_handler; - /// The service type id. + // The service type id. static const service_type_id id; - /// Register a new socket_acceptor with the service. This should be called - /// only after the socket acceptor has been opened. + // Register a new socket_acceptor with the service. This should be called + // only after the socket acceptor has been opened. virtual void register_socket_acceptor(socket_acceptor& acceptor) = 0; - /// Remove a socket acceptor registration from the service. This should be - /// called immediately before the socket acceptor is closed. + // Remove a socket acceptor registration from the service. This should be + // called immediately before the socket acceptor is closed. virtual void deregister_socket_acceptor(socket_acceptor& acceptor) = 0; - /// Start an asynchronous accept on the given socket. The peer_socket object - /// must be valid until the accept's completion handler is invoked. + // Start an asynchronous accept on the given socket. The peer_socket object + // must be valid until the accept's completion handler is invoked. virtual void async_socket_accept(socket_acceptor& acceptor, stream_socket& peer_socket, const accept_handler& handler, completion_context& context) = 0; - /// Start an asynchronous accept on the given socket. The peer_socket and - /// peer_address objects must be valid until the accept's completion handler - /// is invoked. + // Start an asynchronous accept on the given socket. The peer_socket and + // peer_address objects must be valid until the accept's completion handler + // is invoked. virtual void async_socket_accept(socket_acceptor& acceptor, stream_socket& peer_socket, socket_address& peer_address, const accept_handler& handler, completion_context& context) = 0; protected: - /// Associate the given stream_socket with the underlying native handle that - /// was obtained by the acceptor. + // Associate the given stream_socket with the underlying native handle that + // was obtained by the acceptor. static void associate_accepted_stream_socket(socket_acceptor& acceptor, stream_socket& peer_socket, stream_socket::native_type handle); }; +} // namespace detail } // namespace asio #include "asio/detail/pop_options.hpp" -#endif // ASIO_SOCKET_ACCEPTOR_SERVICE_HPP +#endif // ASIO_DETAIL_SOCKET_ACCEPTOR_SERVICE_HPP diff --git a/asio/src/asio/socket_connector_service.cpp b/asio/src/asio/detail/socket_connector_service.cpp similarity index 90% rename from asio/src/asio/socket_connector_service.cpp rename to asio/src/asio/detail/socket_connector_service.cpp index 43744744..a4f0472e 100644 --- a/asio/src/asio/socket_connector_service.cpp +++ b/asio/src/asio/detail/socket_connector_service.cpp @@ -12,9 +12,10 @@ // no claim as to its suitability for any purpose. // -#include "asio/socket_connector_service.hpp" +#include "asio/detail/socket_connector_service.hpp" namespace asio { +namespace detail { const service_type_id socket_connector_service::id; @@ -28,4 +29,5 @@ associate_connected_stream_socket( connector.associate(peer_socket, handle); } +} // namespace detail } // namespace asio diff --git a/asio/src/asio/detail/socket_connector_service.hpp b/asio/src/asio/detail/socket_connector_service.hpp new file mode 100644 index 00000000..3e92a8ac --- /dev/null +++ b/asio/src/asio/detail/socket_connector_service.hpp @@ -0,0 +1,88 @@ +// +// socket_connector_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003 Christopher M. Kohlhoff (chris@kohlhoff.com) +// +// Permission to use, copy, modify, distribute and sell this software and its +// documentation for any purpose is hereby granted without fee, provided that +// the above copyright notice appears in all copies and that both the copyright +// notice and this permission notice appear in supporting documentation. This +// software is provided "as is" without express or implied warranty, and with +// no claim as to its suitability for any purpose. +// + +#ifndef ASIO_DETAIL_SOCKET_CONNECTOR_SERVICE_HPP +#define ASIO_DETAIL_SOCKET_CONNECTOR_SERVICE_HPP + +#include "asio/detail/push_options.hpp" + +#include "asio/service.hpp" +#include "asio/service_type_id.hpp" + +namespace asio { +namespace detail { + +class socket_connector_impl; + +class socket_connector_service + : public virtual service +{ +public: + typedef socket_connector::connect_handler connect_handler; + + // The service type id. + static const service_type_id id; + + /// The native type of the socket connector. This type is dependent on the + /// underlying implementation of the socket layer. + typedef socket_connector_impl* impl_type; + + // Initialise a socket connector to a null implementation. + void nullify(impl_type& impl); + + // Create a new socket connector implementation. + void create(impl_type& impl); + + // Destroy a socket connector implementation. + void destroy(impl_type& impl); + + // Connect the given socket to the peer at the specified address. Throws a + // socket_error exception on failure. + void connect(socket_type& peer_socket, const socket_address& peer_address); + + // Start an asynchronous connect. The peer_socket object must be valid until + // the connect's completion handler is invoked. + void async_connect(peer_socket& peer_socket, + const socket_address& peer_address, const connect_handler& handler, + completion_context& context = completion_context::null()); + + // Register a new socket_connector with the service. This should be called + // only after the socket connector has been opened. + virtual void register_socket_connector(socket_connector& connector) = 0; + + // Remove a socket connector registration from the service. This should be + // called immediately before the socket connector is closed. + virtual void deregister_socket_connector(socket_connector& connector) = 0; + + // Start an asynchronous connect on the given socket. The peer_socket object + // be valid until the connect's completion handler is invoked. + virtual void async_socket_connect(socket_connector& connector, + stream_socket& peer_socket, const socket_address& peer_address, + const connect_handler& handler, completion_context& context) = 0; + +protected: + // Associate the given stream_socket with the underlying native handle that + // was obtained by the connector. + static void associate_connected_stream_socket(socket_connector& connector, + stream_socket& peer_socket, stream_socket::native_type handle); + +private: +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_SOCKET_CONNECTOR_SERVICE_HPP diff --git a/asio/src/asio/stream_socket_service.cpp b/asio/src/asio/detail/stream_socket_service.cpp similarity index 88% rename from asio/src/asio/stream_socket_service.cpp rename to asio/src/asio/detail/stream_socket_service.cpp index 924d067d..fcee13e8 100644 --- a/asio/src/asio/stream_socket_service.cpp +++ b/asio/src/asio/detail/stream_socket_service.cpp @@ -12,10 +12,12 @@ // no claim as to its suitability for any purpose. // -#include "asio/stream_socket_service.hpp" +#include "asio/detail/stream_socket_service.hpp" namespace asio { +namespace detail { const service_type_id stream_socket_service::id; +} // namespace detail } // namespace asio diff --git a/asio/src/asio/stream_socket_service.hpp b/asio/src/asio/detail/stream_socket_service.hpp similarity index 59% rename from asio/src/asio/stream_socket_service.hpp rename to asio/src/asio/detail/stream_socket_service.hpp index c5918022..47e63ed0 100644 --- a/asio/src/asio/stream_socket_service.hpp +++ b/asio/src/asio/detail/stream_socket_service.hpp @@ -12,8 +12,8 @@ // no claim as to its suitability for any purpose. // -#ifndef ASIO_STREAM_SOCKET_SERVICE_HPP -#define ASIO_STREAM_SOCKET_SERVICE_HPP +#ifndef ASIO_DETAIL_STREAM_SOCKET_SERVICE_HPP +#define ASIO_DETAIL_STREAM_SOCKET_SERVICE_HPP #include "asio/detail/push_options.hpp" @@ -22,9 +22,8 @@ #include "asio/stream_socket.hpp" namespace asio { +namespace detail { -/// The stream_socket_service class is a base class for service implementations -/// that provide the functionality required by the stream_socket class. class stream_socket_service : public virtual service { @@ -34,48 +33,49 @@ public: typedef stream_socket::recv_handler recv_handler; typedef stream_socket::recv_n_handler recv_n_handler; - /// The service type id. + // The service type id. static const service_type_id id; - /// Register a new stream socket with the service. This should be called only - /// after the socket has been opened, i.e. after an accept or just before a - /// connect. + // Register a new stream socket with the service. This should be called only + // after the socket has been opened, i.e. after an accept or just before a + // connect. virtual void register_stream_socket(stream_socket& socket) = 0; - /// Remove a stream socket registration from the service. This should be - /// called immediately before the socket is closed. + // Remove a stream socket registration from the service. This should be + // called immediately before the socket is closed. virtual void deregister_stream_socket(stream_socket& socket) = 0; - /// Start an asynchronous send. The data being sent must be valid for the - /// lifetime of the asynchronous operation. + // Start an asynchronous send. The data being sent must be valid for the + // lifetime of the asynchronous operation. virtual void async_stream_socket_send(stream_socket& socket, const void* data, size_t length, const send_handler& handler, completion_context& context) = 0; - /// Start an asynchronous send that will not return until all of the data has - /// been sent or an error occurs. The data being sent must be valid for the - /// lifetime of the asynchronous operation. + // Start an asynchronous send that will not return until all of the data has + // been sent or an error occurs. The data being sent must be valid for the + // lifetime of the asynchronous operation. virtual void async_stream_socket_send_n(stream_socket& socket, const void* data, size_t length, const send_n_handler& handler, completion_context& context) = 0; - /// Start an asynchronous receive. The buffer for the data being received - /// must be valid for the lifetime of the asynchronous operation. + // Start an asynchronous receive. The buffer for the data being received + // must be valid for the lifetime of the asynchronous operation. virtual void async_stream_socket_recv(stream_socket& socket, void* data, size_t max_length, const recv_handler& handler, completion_context& context) = 0; - /// Start an asynchronous receive that will not return until the specified - /// number of bytes has been received or an error occurs. The buffer for the - /// data being received must be valid for the lifetime of the asynchronous - /// operation. + // Start an asynchronous receive that will not return until the specified + // number of bytes has been received or an error occurs. The buffer for the + // data being received must be valid for the lifetime of the asynchronous + // operation. virtual void async_stream_socket_recv_n(stream_socket& socket, void* data, size_t length, const recv_n_handler& handler, completion_context& context) = 0; }; +} // namespace detail } // namespace asio #include "asio/detail/pop_options.hpp" -#endif // ASIO_STREAM_SOCKET_SERVICE_HPP +#endif // ASIO_DETAIL_STREAM_SOCKET_SERVICE_HPP diff --git a/asio/src/asio/detail/timer_queue_provider.cpp b/asio/src/asio/detail/timer_queue_provider.cpp index 35bd30da..a85a665a 100644 --- a/asio/src/asio/detail/timer_queue_provider.cpp +++ b/asio/src/asio/detail/timer_queue_provider.cpp @@ -18,10 +18,6 @@ #include #include "asio/detail/pop_options.hpp" -#include "asio/completion_context.hpp" -#include "asio/demuxer.hpp" -#include "asio/service_unavailable.hpp" - namespace asio { namespace detail { @@ -64,8 +60,8 @@ do_get_service( int timer_queue_provider:: -schedule_timer( - timer_queue& queue, +do_schedule_timer( + void* owner, const boost::xtime& start_time, const boost::xtime& interval, const timer_handler& handler, @@ -77,7 +73,7 @@ schedule_timer( new_event.handler = handler; new_event.interval = interval; new_event.context = &context; - new_event.owner = &queue; + new_event.owner = owner; new_event.id = next_timer_id_++; id_to_timer_.insert(std::make_pair(new_event.id, timer_queue_.insert(std::make_pair(start_time, new_event)))); @@ -98,14 +94,14 @@ namespace void timer_queue_provider:: -cancel_timer( - timer_queue& queue, +do_cancel_timer( + void* owner, int timer_id) { boost::mutex::scoped_lock lock(mutex_); id_to_timer_map::iterator iter = id_to_timer_.find(timer_id); - if (iter != id_to_timer_.end() && iter->second->second.owner == &queue) + if (iter != id_to_timer_.end() && iter->second->second.owner == owner) { timer_queue_.erase(iter->second); id_to_timer_.erase(iter); diff --git a/asio/src/asio/detail/timer_queue_provider.hpp b/asio/src/asio/detail/timer_queue_provider.hpp index 9e0991bc..183208d3 100644 --- a/asio/src/asio/detail/timer_queue_provider.hpp +++ b/asio/src/asio/detail/timer_queue_provider.hpp @@ -23,9 +23,10 @@ #include #include "asio/detail/pop_options.hpp" +#include "asio/demuxer.hpp" #include "asio/completion_context.hpp" #include "asio/service_provider.hpp" -#include "asio/timer_queue_service.hpp" +#include "asio/detail/timer_queue_service.hpp" namespace asio { namespace detail { @@ -41,6 +42,7 @@ public: // Destructor. virtual ~timer_queue_provider(); +private: // Return the service interface corresponding to the given type. virtual service* do_get_service(const service_type_id& service_type); @@ -48,18 +50,16 @@ public: // interval until the timer is cancelled. A zero interval means that the // timer will fire once only. The id of the new timer is returned so that it // may be cancelled. - virtual int schedule_timer(timer_queue& queue, + virtual int do_schedule_timer(void* owner, const boost::xtime& start_time, const boost::xtime& interval, const timer_handler& handler, completion_context& context); // Cancel the timer with the given id. - virtual void cancel_timer(timer_queue& queue, int timer_id); + virtual void do_cancel_timer(void* owner, int timer_id); -private: // Loop for expiring timers until it is time to shut down. void expire_timers(); -private: // The demuxer that owns this provider. demuxer& demuxer_; @@ -90,7 +90,7 @@ private: boost::function0 handler; boost::xtime interval; completion_context* context; - timer_queue* owner; + void* owner; int id; }; diff --git a/asio/src/asio/timer_queue.cpp b/asio/src/asio/detail/timer_queue_service.cpp similarity index 62% rename from asio/src/asio/timer_queue.cpp rename to asio/src/asio/detail/timer_queue_service.cpp index 31403286..5b14c115 100644 --- a/asio/src/asio/timer_queue.cpp +++ b/asio/src/asio/detail/timer_queue_service.cpp @@ -1,6 +1,6 @@ // -// timer_queue.cpp -// ~~~~~~~~~~~~~~~ +// timer_queue_service.cpp +// ~~~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2003 Christopher M. Kohlhoff (chris@kohlhoff.com) // @@ -12,28 +12,17 @@ // no claim as to its suitability for any purpose. // -#include "asio/timer_queue.hpp" -#include "asio/timer_queue_service.hpp" -#include "asio/demuxer.hpp" +#include "asio/detail/timer_queue_service.hpp" namespace asio { +namespace detail { -timer_queue:: -timer_queue( - demuxer& d) - : service_(dynamic_cast( - d.get_service(timer_queue_service::id))) -{ -} - -timer_queue:: -~timer_queue() -{ -} +const service_type_id timer_queue_service::id; int -timer_queue:: +timer_queue_service:: schedule_timer( + void* owner, const boost::xtime& start_time, const timer_handler& handler, completion_context& context) @@ -41,28 +30,29 @@ schedule_timer( boost::xtime interval; interval.sec = 0; interval.nsec = 0; - return service_.schedule_timer(*this, start_time, interval, handler, - context); + do_schedule_timer(owner, start_time, interval, handler, context); } int -timer_queue:: +timer_queue_service:: schedule_timer( + void* owner, const boost::xtime& start_time, const boost::xtime& interval, const timer_handler& handler, completion_context& context) { - return service_.schedule_timer(*this, start_time, interval, handler, - context); + do_schedule_timer(owner, start_time, interval, handler, context); } void -timer_queue:: +timer_queue_service:: cancel_timer( + void* owner, int timer_id) { - service_.cancel_timer(*this, timer_id); + do_cancel_timer(owner, timer_id); } +} // namespace detail } // namespace asio diff --git a/asio/src/asio/detail/timer_queue_service.hpp b/asio/src/asio/detail/timer_queue_service.hpp new file mode 100644 index 00000000..7f7d7fab --- /dev/null +++ b/asio/src/asio/detail/timer_queue_service.hpp @@ -0,0 +1,76 @@ +// +// timer_queue_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003 Christopher M. Kohlhoff (chris@kohlhoff.com) +// +// Permission to use, copy, modify, distribute and sell this software and its +// documentation for any purpose is hereby granted without fee, provided that +// the above copyright notice appears in all copies and that both the copyright +// notice and this permission notice appear in supporting documentation. This +// software is provided "as is" without express or implied warranty, and with +// no claim as to its suitability for any purpose. +// + +#ifndef ASIO_DETAIL_TIMER_QUEUE_SERVICE_HPP +#define ASIO_DETAIL_TIMER_QUEUE_SERVICE_HPP + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/completion_context.hpp" +#include "asio/service.hpp" +#include "asio/service_type_id.hpp" + +namespace asio { +namespace detail { + +class timer_queue_service + : public virtual service +{ +public: + // The service type id. + static const service_type_id id; + + /// The handler for when a timer expires. + typedef boost::function0 timer_handler; + + /// Schedule a timer to fire once at the given start_time. The id of the new + /// timer is returned so that it may be cancelled. + int schedule_timer(void* owner, const boost::xtime& start_time, + const timer_handler& handler, + completion_context& context = completion_context::null()); + + /// Schedule a timer to fire first after at the start time, and then every + /// interval until the timer is cancelled. The id of the new timer is + /// returned so that it may be cancelled. + int schedule_timer(void* owner, const boost::xtime& start_time, + const boost::xtime& interval, const timer_handler& handler, + completion_context& context = completion_context::null()); + + /// Cancel the timer with the given id. + void cancel_timer(void* owner, int timer_id); + +private: + // Schedule a timer to fire first after at the start time, and then every + // interval until the timer is cancelled. A zero interval means that the + // timer will fire once only. The id of the new timer is returned so that it + // may be cancelled. + virtual int do_schedule_timer(void* owner, const boost::xtime& start_time, + const boost::xtime& interval, const timer_handler& handler, + completion_context& context) = 0; + + // Cancel the timer with the given id. + virtual void do_cancel_timer(void* owner, int timer_id) = 0; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_TIMER_QUEUE_SERVICE_HPP diff --git a/asio/src/asio/detail/win_iocp_provider.hpp b/asio/src/asio/detail/win_iocp_provider.hpp index f83bee5b..cc0d9df6 100644 --- a/asio/src/asio/detail/win_iocp_provider.hpp +++ b/asio/src/asio/detail/win_iocp_provider.hpp @@ -21,10 +21,10 @@ #include "asio/completion_context_locker.hpp" #include "asio/demuxer_service.hpp" -#include "asio/dgram_socket_service.hpp" #include "asio/service_provider.hpp" -#include "asio/stream_socket_service.hpp" #include "asio/detail/demuxer_thread_pool.hpp" +#include "asio/detail/dgram_socket_service.hpp" +#include "asio/detail/stream_socket_service.hpp" namespace asio { namespace detail { diff --git a/asio/src/asio/dgram_socket.cpp b/asio/src/asio/dgram_socket.cpp deleted file mode 100644 index 2ea49a93..00000000 --- a/asio/src/asio/dgram_socket.cpp +++ /dev/null @@ -1,157 +0,0 @@ -// -// dgram_socket.cpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003 Christopher M. Kohlhoff (chris@kohlhoff.com) -// -// Permission to use, copy, modify, distribute and sell this software and its -// documentation for any purpose is hereby granted without fee, provided that -// the above copyright notice appears in all copies and that both the copyright -// notice and this permission notice appear in supporting documentation. This -// software is provided "as is" without express or implied warranty, and with -// no claim as to its suitability for any purpose. -// - -#include "asio/dgram_socket.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/demuxer.hpp" -#include "asio/dgram_socket_service.hpp" -#include "asio/socket_address.hpp" -#include "asio/socket_error.hpp" -#include "asio/detail/socket_holder.hpp" -#include "asio/detail/socket_ops.hpp" - -namespace asio { - -dgram_socket:: -dgram_socket( - demuxer& d) - : service_(dynamic_cast( - d.get_service(dgram_socket_service::id))), - handle_(detail::invalid_socket) -{ -} - -dgram_socket:: -dgram_socket( - demuxer& d, - const socket_address& addr) - : service_(dynamic_cast( - d.get_service(dgram_socket_service::id))), - handle_(detail::invalid_socket) -{ - open(addr); -} - -dgram_socket:: -~dgram_socket() -{ - close(); -} - -void -dgram_socket:: -open( - const socket_address& addr) -{ - assert(handle_ == detail::invalid_socket); - - detail::socket_holder sock(detail::socket_ops::socket(addr.family(), - SOCK_DGRAM, IPPROTO_UDP)); - if (sock.get() == detail::invalid_socket) - boost::throw_exception(socket_error(detail::socket_ops::get_error())); - - int reuse = 1; - detail::socket_ops::setsockopt(sock.get(), SOL_SOCKET, SO_REUSEADDR, &reuse, - sizeof(reuse)); - - if (detail::socket_ops::bind(sock.get(), addr.native_address(), - addr.native_size()) == detail::socket_error_retval) - boost::throw_exception(socket_error(detail::socket_ops::get_error())); - - handle_ = sock.release(); - - service_.register_dgram_socket(*this); -} - -void -dgram_socket:: -close() -{ - if (handle_ != detail::invalid_socket) - { - service_.deregister_dgram_socket(*this); - detail::socket_ops::close(handle_); - handle_ = detail::invalid_socket; - } -} - -dgram_socket::native_type -dgram_socket:: -native_handle() const -{ - return handle_; -} - -size_t -dgram_socket:: -sendto( - const void* data, - size_t length, - const socket_address& destination) -{ - int bytes_sent = detail::socket_ops::sendto(handle_, data, length, 0, - destination.native_address(), destination.native_size()); - if (bytes_sent < 0) - boost::throw_exception(socket_error(detail::socket_ops::get_error())); - return bytes_sent; -} - -void -dgram_socket:: -async_sendto( - const void* data, - size_t length, - const socket_address& destination, - const sendto_handler& handler, - completion_context& context) -{ - service_.async_dgram_socket_sendto(*this, data, length, destination, handler, - context); -} - -size_t -dgram_socket:: -recvfrom( - void* data, - size_t max_length, - socket_address& sender_address) -{ - detail::socket_addr_len_type addr_len = sender_address.native_size(); - int bytes_recvd = detail::socket_ops::recvfrom(handle_, data, max_length, 0, - sender_address.native_address(), &addr_len); - if (bytes_recvd < 0) - boost::throw_exception(socket_error(detail::socket_ops::get_error())); - sender_address.native_size(addr_len); - return bytes_recvd; -} - -void -dgram_socket:: -async_recvfrom( - void* data, - size_t max_length, - socket_address& sender_address, - const recvfrom_handler& handler, - completion_context& context) -{ - service_.async_dgram_socket_recvfrom(*this, data, max_length, sender_address, - handler, context); -} - -} // namespace asio diff --git a/asio/src/asio/dgram_socket.hpp b/asio/src/asio/dgram_socket.hpp index dd83f253..6b6dba05 100644 --- a/asio/src/asio/dgram_socket.hpp +++ b/asio/src/asio/dgram_socket.hpp @@ -17,88 +17,13 @@ #include "asio/detail/push_options.hpp" -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/completion_context.hpp" -#include "asio/detail/socket_types.hpp" +#include "asio/dgram_socket.hpp" +#include "asio/detail/dgram_socket_service.hpp" namespace asio { -class demuxer; -class dgram_socket_service; -class socket_address; -class socket_error; - -/// The dgram_socket class provides asynchronous and blocking datagram-oriented -/// socket functionality. -class dgram_socket - : private boost::noncopyable -{ -public: - /// The native type of the socket acceptor. This type is dependent on the - /// underlying implementation of the socket layer. - typedef detail::socket_type native_type; - - /// Construct a dgram_socket without opening it. The socket needs to be - /// opened before data can be sent or received on it. - explicit dgram_socket(demuxer& d); - - /// Construct a dgram_socket opened on the given address. - dgram_socket(demuxer& d, const socket_address& address); - - /// Destructor. - ~dgram_socket(); - - /// Open the socket on the given address. - void open(const socket_address& address); - - /// Close the socket. - void close(); - - /// Get the underlying handle in the native type. - native_type native_handle() const; - - /// Send a datagram to the specified address. Returns the number of bytes - /// sent. Throws a socket_error exception on failure. - size_t sendto(const void* data, size_t length, - const socket_address& destination); - - /// The handler when a sendto operation is completed. The first argument is - /// the error code, the second is the number of bytes sent. - typedef boost::function2 sendto_handler; - - /// Start an asynchronous send. The data being sent must be valid for the - /// lifetime of the asynchronous operation. - void async_sendto(const void* data, size_t length, - const socket_address& destination, const sendto_handler& handler, - completion_context& context = completion_context::null()); - - /// Receive a datagram with the address of the sender. Returns the number of - /// bytes received. Throws a socket_error exception on failure. - size_t recvfrom(void* data, size_t max_length, - socket_address& sender_address); - - /// The handler when a recvfrom operation is completed. The first argument is - /// the error code, the second is the number of bytes received. - typedef boost::function2 recvfrom_handler; - - /// Start an asynchronous receive. The buffer for the data being received and - /// the sender_address obejct must both be valid for the lifetime of the - /// asynchronous operation. - void async_recvfrom(void* data, size_t max_length, - socket_address& sender_address, const recvfrom_handler& handler, - completion_context& context = completion_context::null()); - -private: - /// The backend service implementation. - dgram_socket_service& service_; - - /// The underlying native handle. - native_type handle_; -}; +/// Typedef for the typical usage of dgram_socket. +typedef basic_dgram_socket dgram_socket; } // namespace asio diff --git a/asio/src/asio/dgram_socket_service.cpp b/asio/src/asio/dgram_socket_service.cpp deleted file mode 100644 index 101d9b31..00000000 --- a/asio/src/asio/dgram_socket_service.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// -// dgram_socket_service.cpp -// ~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003 Christopher M. Kohlhoff (chris@kohlhoff.com) -// -// Permission to use, copy, modify, distribute and sell this software and its -// documentation for any purpose is hereby granted without fee, provided that -// the above copyright notice appears in all copies and that both the copyright -// notice and this permission notice appear in supporting documentation. This -// software is provided "as is" without express or implied warranty, and with -// no claim as to its suitability for any purpose. -// - -#include "asio/dgram_socket_service.hpp" - -namespace asio { - -const service_type_id dgram_socket_service::id; - -} // namespace asio diff --git a/asio/src/asio/dgram_socket_service.hpp b/asio/src/asio/dgram_socket_service.hpp deleted file mode 100644 index 9bde89da..00000000 --- a/asio/src/asio/dgram_socket_service.hpp +++ /dev/null @@ -1,64 +0,0 @@ -// -// dgram_socket_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003 Christopher M. Kohlhoff (chris@kohlhoff.com) -// -// Permission to use, copy, modify, distribute and sell this software and its -// documentation for any purpose is hereby granted without fee, provided that -// the above copyright notice appears in all copies and that both the copyright -// notice and this permission notice appear in supporting documentation. This -// software is provided "as is" without express or implied warranty, and with -// no claim as to its suitability for any purpose. -// - -#ifndef ASIO_DGRAM_SOCKET_SERVICE_HPP -#define ASIO_DGRAM_SOCKET_SERVICE_HPP - -#include "asio/detail/push_options.hpp" - -#include "asio/service.hpp" -#include "asio/service_type_id.hpp" -#include "asio/dgram_socket.hpp" - -namespace asio { - -/// The dgram_socket_service class is a base class for service implementations -/// that provide the functionality required by the dgram_socket class. -class dgram_socket_service - : public virtual service -{ -public: - typedef dgram_socket::sendto_handler sendto_handler; - typedef dgram_socket::recvfrom_handler recvfrom_handler; - - /// The service type id. - static const service_type_id id; - - /// Register a new dgram socket with the service. This should be called only - /// after the socket has been opened. - virtual void register_dgram_socket(dgram_socket& socket) = 0; - - /// Remove a dgram socket registration from the service. This should be - /// called immediately before the socket is closed. - virtual void deregister_dgram_socket(dgram_socket& socket) = 0; - - /// Start an asynchronous send. The data being sent must be valid for the - /// lifetime of the asynchronous operation. - virtual void async_dgram_socket_sendto(dgram_socket& socket, - const void* data, size_t length, const socket_address& destination, - const sendto_handler& handler, completion_context& context) = 0; - - /// Start an asynchronous receive. The buffer for the data being received and - /// the sender_address obejct must both be valid for the lifetime of the - /// asynchronous operation. - virtual void async_dgram_socket_recvfrom(dgram_socket& socket, void* data, - size_t max_length, socket_address& sender_address, - const recvfrom_handler& handler, completion_context& context) = 0; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DGRAM_SOCKET_SERVICE_HPP diff --git a/asio/src/asio/socket_acceptor.cpp b/asio/src/asio/socket_acceptor.cpp index 04a92b0f..0083734d 100644 --- a/asio/src/asio/socket_acceptor.cpp +++ b/asio/src/asio/socket_acceptor.cpp @@ -20,9 +20,9 @@ #include "asio/detail/pop_options.hpp" #include "asio/demuxer.hpp" -#include "asio/socket_acceptor_service.hpp" #include "asio/socket_address.hpp" #include "asio/socket_error.hpp" +#include "asio/detail/socket_acceptor_service.hpp" #include "asio/detail/socket_holder.hpp" #include "asio/detail/socket_ops.hpp" @@ -31,8 +31,8 @@ namespace asio { socket_acceptor:: socket_acceptor( demuxer& d) - : service_(dynamic_cast( - d.get_service(socket_acceptor_service::id))), + : service_(dynamic_cast( + d.get_service(detail::socket_acceptor_service::id))), handle_(detail::invalid_socket) { } @@ -42,8 +42,8 @@ socket_acceptor( demuxer& d, const socket_address& addr, int listen_queue) - : service_(dynamic_cast( - d.get_service(socket_acceptor_service::id))), + : service_(dynamic_cast( + d.get_service(detail::socket_acceptor_service::id))), handle_(detail::invalid_socket) { open(addr, listen_queue); diff --git a/asio/src/asio/socket_acceptor.hpp b/asio/src/asio/socket_acceptor.hpp index 0bae4b65..9a0b6639 100644 --- a/asio/src/asio/socket_acceptor.hpp +++ b/asio/src/asio/socket_acceptor.hpp @@ -29,9 +29,9 @@ namespace asio { class demuxer; -class socket_acceptor_service; class socket_address; class socket_error; +namespace detail { class socket_acceptor_service; } /// The socket_acceptor class is used for accepting new socket connections. class socket_acceptor @@ -119,7 +119,7 @@ public: private: /// The socket_acceptor_service class is permitted to call the associate() /// function. - friend class socket_acceptor_service; + friend class detail::socket_acceptor_service; // Accept a new connection. Throws a socket_error exception on failure. void accept_i(stream_socket& peer_socket); @@ -144,7 +144,7 @@ private: stream_socket::native_type handle); /// The backend service implementation. - socket_acceptor_service& service_; + detail::socket_acceptor_service& service_; /// The underlying native handle. native_type handle_; diff --git a/asio/src/asio/socket_connector.cpp b/asio/src/asio/socket_connector.cpp index b53bd62f..76817038 100644 --- a/asio/src/asio/socket_connector.cpp +++ b/asio/src/asio/socket_connector.cpp @@ -20,10 +20,10 @@ #include "asio/detail/pop_options.hpp" #include "asio/demuxer.hpp" -#include "asio/socket_connector_service.hpp" #include "asio/socket_address.hpp" #include "asio/socket_error.hpp" #include "asio/detail/socket_connector_impl.hpp" +#include "asio/detail/socket_connector_service.hpp" #include "asio/detail/socket_holder.hpp" #include "asio/detail/socket_ops.hpp" @@ -32,8 +32,8 @@ namespace asio { socket_connector:: socket_connector( demuxer& d) - : service_(dynamic_cast( - d.get_service(socket_connector_service::id))), + : service_(dynamic_cast( + d.get_service(detail::socket_connector_service::id))), impl_(new detail::socket_connector_impl) { service_.register_socket_connector(*this); diff --git a/asio/src/asio/socket_connector.hpp b/asio/src/asio/socket_connector.hpp index 9f02e8a7..0e17e14d 100644 --- a/asio/src/asio/socket_connector.hpp +++ b/asio/src/asio/socket_connector.hpp @@ -29,9 +29,9 @@ namespace asio { class demuxer; -class socket_connector_service; class socket_address; class socket_error; +namespace detail { class socket_connector_service; } namespace detail { class socket_connector_impl; } /// The socket_connector class is used to connect a socket to a remote @@ -94,7 +94,7 @@ public: private: /// The socket_connector_service is permitted to call the associate() /// function. - friend class socket_connector_service; + friend class detail::socket_connector_service; // Connect the given socket to the peer at the specified address. Throws a // socket_error exception on failure. @@ -112,7 +112,7 @@ private: stream_socket::native_type handle); /// The backend service implementation. - socket_connector_service& service_; + detail::socket_connector_service& service_; /// The underlying implementation. detail::socket_connector_impl* impl_; diff --git a/asio/src/asio/socket_connector_service.hpp b/asio/src/asio/socket_connector_service.hpp deleted file mode 100644 index ca80d820..00000000 --- a/asio/src/asio/socket_connector_service.hpp +++ /dev/null @@ -1,64 +0,0 @@ -// -// socket_connector_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003 Christopher M. Kohlhoff (chris@kohlhoff.com) -// -// Permission to use, copy, modify, distribute and sell this software and its -// documentation for any purpose is hereby granted without fee, provided that -// the above copyright notice appears in all copies and that both the copyright -// notice and this permission notice appear in supporting documentation. This -// software is provided "as is" without express or implied warranty, and with -// no claim as to its suitability for any purpose. -// - -#ifndef ASIO_SOCKET_CONNECTOR_SERVICE_HPP -#define ASIO_SOCKET_CONNECTOR_SERVICE_HPP - -#include "asio/detail/push_options.hpp" - -#include "asio/service.hpp" -#include "asio/service_type_id.hpp" -#include "asio/socket_connector.hpp" -#include "asio/stream_socket.hpp" - -namespace asio { - -/// The socket_connector_service class is a base class for service -/// implementations that provide the functionality required by the -/// socket_connector class. -class socket_connector_service - : public virtual service -{ -public: - typedef socket_connector::connect_handler connect_handler; - - /// The service type id. - static const service_type_id id; - - /// Register a new socket_connector with the service. This should be called - /// only after the socket connector has been opened. - virtual void register_socket_connector(socket_connector& connector) = 0; - - /// Remove a socket connector registration from the service. This should be - /// called immediately before the socket connector is closed. - virtual void deregister_socket_connector(socket_connector& connector) = 0; - - /// Start an asynchronous connect on the given socket. The peer_socket object - /// be valid until the connect's completion handler is invoked. - virtual void async_socket_connect(socket_connector& connector, - stream_socket& peer_socket, const socket_address& peer_address, - const connect_handler& handler, completion_context& context) = 0; - -protected: - /// Associate the given stream_socket with the underlying native handle that - /// was obtained by the connector. - static void associate_connected_stream_socket(socket_connector& connector, - stream_socket& peer_socket, stream_socket::native_type handle); -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SOCKET_CONNECTOR_SERVICE_HPP diff --git a/asio/src/asio/stream_socket.cpp b/asio/src/asio/stream_socket.cpp index b39e38a1..61c98246 100644 --- a/asio/src/asio/stream_socket.cpp +++ b/asio/src/asio/stream_socket.cpp @@ -21,16 +21,16 @@ #include "asio/demuxer.hpp" #include "asio/socket_error.hpp" -#include "asio/stream_socket_service.hpp" #include "asio/detail/socket_ops.hpp" +#include "asio/detail/stream_socket_service.hpp" namespace asio { stream_socket:: stream_socket( demuxer& d) - : service_(dynamic_cast( - d.get_service(stream_socket_service::id))), + : service_(dynamic_cast( + d.get_service(detail::stream_socket_service::id))), handle_(detail::invalid_socket) { } diff --git a/asio/src/asio/stream_socket.hpp b/asio/src/asio/stream_socket.hpp index efbe30a5..ecff0584 100644 --- a/asio/src/asio/stream_socket.hpp +++ b/asio/src/asio/stream_socket.hpp @@ -31,7 +31,7 @@ class demuxer; class socket_acceptor; class socket_connector; class socket_error; -class stream_socket_service; +namespace detail { class stream_socket_service; } /// The stream_socket class provides asynchronous and blocking stream-oriented /// socket functionality. @@ -62,6 +62,9 @@ public: /// Get the underlying handle in the native type. native_type native_handle() const; + /// Attach a new socket implementation. + void set_impl(native_type impl); + /// Send the given data to the peer. Returns the number of bytes sent or /// 0 if the connection was closed cleanly. Throws a socket_error exception /// on failure. @@ -139,7 +142,7 @@ private: void associate(native_type handle); /// The backend service implementation. - stream_socket_service& service_; + detail::stream_socket_service& service_; /// The underlying native handle. native_type handle_; diff --git a/asio/src/asio/timer_queue.hpp b/asio/src/asio/timer_queue.hpp index 124ece8c..c7c934f7 100644 --- a/asio/src/asio/timer_queue.hpp +++ b/asio/src/asio/timer_queue.hpp @@ -17,53 +17,13 @@ #include "asio/detail/push_options.hpp" -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/completion_context.hpp" +#include "asio/basic_timer_queue.hpp" +#include "asio/detail/timer_queue_service.hpp" namespace asio { -class demuxer; -class timer_queue_service; - -/// The timer_queue class provides asynchronous timer functionality. -class timer_queue - : private boost::noncopyable -{ -public: - /// Constructor. - explicit timer_queue(demuxer& d); - - /// Destructor. - ~timer_queue(); - - /// The handler for when a timer expires. - typedef boost::function0 timer_handler; - - /// Schedule a timer to fire once at the given start_time. The id of the new - /// timer is returned so that it may be cancelled. - int schedule_timer(const boost::xtime& start_time, - const timer_handler& handler, - completion_context& context = completion_context::null()); - - /// Schedule a timer to fire first after at the start time, and then every - /// interval until the timer is cancelled. The id of the new timer is - /// returned so that it may be cancelled. - int schedule_timer(const boost::xtime& start_time, - const boost::xtime& interval, const timer_handler& handler, - completion_context& context = completion_context::null()); - - /// Cancel the timer with the given id. - void cancel_timer(int timer_id); - -private: - /// The backend service implementation. - timer_queue_service& service_; -}; +/// Typedef for the typical usage of timer_queue. +typedef basic_timer_queue timer_queue; } // namespace asio diff --git a/asio/src/asio/timer_queue_service.cpp b/asio/src/asio/timer_queue_service.cpp deleted file mode 100644 index f5733f3b..00000000 --- a/asio/src/asio/timer_queue_service.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// -// timer_queue_service.cpp -// ~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003 Christopher M. Kohlhoff (chris@kohlhoff.com) -// -// Permission to use, copy, modify, distribute and sell this software and its -// documentation for any purpose is hereby granted without fee, provided that -// the above copyright notice appears in all copies and that both the copyright -// notice and this permission notice appear in supporting documentation. This -// software is provided "as is" without express or implied warranty, and with -// no claim as to its suitability for any purpose. -// - -#include "asio/timer_queue_service.hpp" - -namespace asio { - -const service_type_id timer_queue_service::id; - -} // namespace asio diff --git a/asio/src/asio/timer_queue_service.hpp b/asio/src/asio/timer_queue_service.hpp deleted file mode 100644 index 53bd01f6..00000000 --- a/asio/src/asio/timer_queue_service.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// -// timer_queue_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003 Christopher M. Kohlhoff (chris@kohlhoff.com) -// -// Permission to use, copy, modify, distribute and sell this software and its -// documentation for any purpose is hereby granted without fee, provided that -// the above copyright notice appears in all copies and that both the copyright -// notice and this permission notice appear in supporting documentation. This -// software is provided "as is" without express or implied warranty, and with -// no claim as to its suitability for any purpose. -// - -#ifndef ASIO_TIMER_QUEUE_SERVICE_HPP -#define ASIO_TIMER_QUEUE_SERVICE_HPP - -#include "asio/detail/push_options.hpp" - -#include "asio/service.hpp" -#include "asio/service_type_id.hpp" -#include "asio/timer_queue.hpp" - -namespace asio { - -/// The timer_queue_service class is a base class for service implementations -/// that provide the functionality required by the timer_queue class. -class timer_queue_service - : public virtual service -{ -public: - typedef timer_queue::timer_handler timer_handler; - - /// The service type id. - static const service_type_id id; - - /// Schedule a timer to fire first after at the start time, and then every - /// interval until the timer is cancelled. A zero interval means that the - /// timer will fire once only. The id of the new timer is returned so that it - /// may be cancelled. - virtual int schedule_timer(timer_queue& queue, - const boost::xtime& start_time, const boost::xtime& interval, - const timer_handler& handler, completion_context& context) = 0; - - /// Cancel the timer with the given id. - virtual void cancel_timer(timer_queue& queue, int timer_id) = 0; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_TIMER_QUEUE_SERVICE_HPP