Finished turning the socket classes into templates.
This commit is contained in:
parent
672cc09bb1
commit
09641826f0
@ -17,11 +17,8 @@ ___lib_libasio_a_SOURCES = \
|
||||
asio/service_provider.cpp \
|
||||
asio/service_provider_factory.cpp \
|
||||
asio/service_unavailable.cpp \
|
||||
asio/socket_acceptor.cpp \
|
||||
asio/socket_address.cpp \
|
||||
asio/socket_connector.cpp \
|
||||
asio/socket_error.cpp \
|
||||
asio/stream_socket.cpp \
|
||||
asio/detail/default_service_provider_factory.cpp \
|
||||
asio/detail/demuxer_thread_pool.cpp \
|
||||
asio/detail/dgram_socket_service.cpp \
|
||||
@ -43,6 +40,9 @@ ___lib_libasio_a_SOURCES = \
|
||||
nobase_include_HEADERS = \
|
||||
asio.hpp \
|
||||
asio/basic_dgram_socket.hpp \
|
||||
asio/basic_socket_acceptor.hpp \
|
||||
asio/basic_socket_connector.hpp \
|
||||
asio/basic_stream_socket.hpp \
|
||||
asio/basic_timer_queue.hpp \
|
||||
asio/buffered_recv_stream.hpp \
|
||||
asio/buffered_send_stream.hpp \
|
||||
|
@ -16,6 +16,9 @@
|
||||
#define ASIO_HPP
|
||||
|
||||
#include "asio/basic_dgram_socket.hpp"
|
||||
#include "asio/basic_socket_acceptor.hpp"
|
||||
#include "asio/basic_socket_connector.hpp"
|
||||
#include "asio/basic_stream_socket.hpp"
|
||||
#include "asio/basic_timer_queue.hpp"
|
||||
#include "asio/buffered_recv_stream.hpp"
|
||||
#include "asio/buffered_send_stream.hpp"
|
||||
@ -38,6 +41,7 @@
|
||||
#include "asio/socket_address.hpp"
|
||||
#include "asio/socket_connector.hpp"
|
||||
#include "asio/socket_error.hpp"
|
||||
#include "asio/stream_socket.hpp"
|
||||
#include "asio/timer_queue.hpp"
|
||||
|
||||
#endif // ASIO_HPP
|
||||
|
@ -27,7 +27,6 @@
|
||||
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
|
||||
@ -37,20 +36,24 @@ class basic_dgram_socket
|
||||
: private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
/// The native implementation type of the dgram socket.
|
||||
typedef typename Service::impl_type impl_type;
|
||||
/// The type of the service that will be used to provide socket operations.
|
||||
typedef Service service_type;
|
||||
|
||||
/// Construct a dgram_socket without opening it. The socket needs to be
|
||||
/// The native implementation type of the dgram socket.
|
||||
typedef typename service_type::impl_type impl_type;
|
||||
|
||||
/// Construct a basic_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<Service&>(d.get_service(Service::id)))
|
||||
: service_(dynamic_cast<service_type&>(d.get_service(service_type::id))),
|
||||
impl_(service_type::invalid_impl)
|
||||
{
|
||||
service_.nullify(impl_);
|
||||
}
|
||||
|
||||
/// Construct a dgram_socket opened on the given address.
|
||||
/// Construct a basic_dgram_socket opened on the given address.
|
||||
basic_dgram_socket(demuxer& d, const socket_address& address)
|
||||
: service_(dynamic_cast<Service&>(d.get_service(Service::id)))
|
||||
: service_(dynamic_cast<service_type&>(d.get_service(service_type::id))),
|
||||
impl_(service_type::invalid_impl)
|
||||
{
|
||||
service_.create(impl_, address);
|
||||
}
|
||||
@ -79,13 +82,6 @@ public:
|
||||
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,
|
||||
@ -96,7 +92,7 @@ public:
|
||||
|
||||
/// 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;
|
||||
typedef typename service_type::sendto_handler sendto_handler;
|
||||
|
||||
/// Start an asynchronous send. The data being sent must be valid for the
|
||||
/// lifetime of the asynchronous operation.
|
||||
@ -117,7 +113,7 @@ public:
|
||||
|
||||
/// 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;
|
||||
typedef typename service_type::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
|
||||
@ -132,7 +128,7 @@ public:
|
||||
|
||||
private:
|
||||
/// The backend service implementation.
|
||||
Service& service_;
|
||||
service_type& service_;
|
||||
|
||||
/// The underlying native implementation.
|
||||
impl_type impl_;
|
||||
|
169
asio/src/asio/basic_socket_acceptor.hpp
Normal file
169
asio/src/asio/basic_socket_acceptor.hpp
Normal file
@ -0,0 +1,169 @@
|
||||
//
|
||||
// basic_socket_acceptor.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_SOCKET_ACCEPTOR_HPP
|
||||
#define ASIO_BASIC_SOCKET_ACCEPTOR_HPP
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/completion_context.hpp"
|
||||
#include "asio/demuxer.hpp"
|
||||
|
||||
namespace asio {
|
||||
|
||||
class socket_address;
|
||||
|
||||
/// The basic_socket_acceptor class template is used for accepting new socket
|
||||
/// connections. Most applications would simply use the socket_acceptor
|
||||
/// typedef.
|
||||
template <typename Service>
|
||||
class basic_socket_acceptor
|
||||
: private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
/// The type of the service that will be used to provide accept operations.
|
||||
typedef Service service_type;
|
||||
|
||||
/// The native implementation type of the socket acceptor.
|
||||
typedef typename service_type::impl_type impl_type;
|
||||
|
||||
/// Constructor an acceptor without opening it. The acceptor needs to be
|
||||
/// opened before it can accept new connections.
|
||||
explicit basic_socket_acceptor(demuxer& d)
|
||||
: service_(dynamic_cast<service_type&>(d.get_service(service_type::id))),
|
||||
impl_(service_type::invalid_impl)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct an acceptor opened on the given address.
|
||||
basic_socket_acceptor(demuxer& d, const socket_address& addr)
|
||||
: service_(dynamic_cast<service_type&>(d.get_service(service_type::id))),
|
||||
impl_(service_type::invalid_impl)
|
||||
{
|
||||
service_.create(impl_, addr);
|
||||
}
|
||||
|
||||
/// Construct an acceptor opened on the given address and with the listen
|
||||
/// queue set to the given number of connections.
|
||||
basic_socket_acceptor(demuxer& d, const socket_address& addr,
|
||||
int listen_queue)
|
||||
: service_(dynamic_cast<service_type&>(d.get_service(service_type::id))),
|
||||
impl_(service_type::invalid_impl)
|
||||
{
|
||||
service_.create(impl_, addr, listen_queue);
|
||||
}
|
||||
|
||||
/// Destructor.
|
||||
~basic_socket_acceptor()
|
||||
{
|
||||
service_.destroy(impl_);
|
||||
}
|
||||
|
||||
/// Open the acceptor using the given address.
|
||||
void open(const socket_address& addr)
|
||||
{
|
||||
service_.create(impl_, addr);
|
||||
}
|
||||
|
||||
/// Open the acceptor using the given address and length of the listen queue.
|
||||
void open(const socket_address& addr, int listen_queue)
|
||||
{
|
||||
service_.create(impl_, addr, listen_queue);
|
||||
}
|
||||
|
||||
/// Close the acceptor.
|
||||
void close()
|
||||
{
|
||||
service_.destroy(impl_);
|
||||
}
|
||||
|
||||
/// Get the underlying implementation in the native type.
|
||||
impl_type impl() const
|
||||
{
|
||||
return impl_;
|
||||
}
|
||||
|
||||
/// Accept a new connection. Throws a socket_error exception on failure.
|
||||
template <typename Stream>
|
||||
void accept(Stream& peer_socket)
|
||||
{
|
||||
service_.accept(impl_, peer_socket.lowest_layer());
|
||||
}
|
||||
|
||||
/// Accept a new connection. Throws a socket_error exception on failure.
|
||||
template <typename Stream>
|
||||
void accept(Stream& peer_socket, socket_address& peer_address)
|
||||
{
|
||||
service_.accept(impl_, peer_socket.lowest_layer(), peer_address);
|
||||
}
|
||||
|
||||
/// The type of a handler called when the asynchronous accept completes. The
|
||||
/// only argument is the error code.
|
||||
typedef typename service_type::accept_handler accept_handler;
|
||||
|
||||
/// Start an asynchronous accept. The peer_socket object must be valid until
|
||||
/// the accept's completion handler is invoked.
|
||||
template <typename Stream>
|
||||
void async_accept(Stream& peer_socket, const accept_handler& handler)
|
||||
{
|
||||
service_.async_accept(impl_, peer_socket.lowest_layer(), handler,
|
||||
completion_context::null());
|
||||
}
|
||||
|
||||
/// Start an asynchronous accept. The peer_socket object must be valid until
|
||||
/// the accept's completion handler is invoked.
|
||||
template <typename Stream>
|
||||
void async_accept(Stream& peer_socket, const accept_handler& handler,
|
||||
completion_context& context)
|
||||
{
|
||||
service_.async_accept(impl_, peer_socket.lowest_layer(), handler, context);
|
||||
}
|
||||
|
||||
/// Start an asynchronous accept. The peer_socket and peer_address objects
|
||||
/// must be valid until the accept's completion handler is invoked.
|
||||
template <typename Stream>
|
||||
void async_accept(Stream& peer_socket, socket_address& peer_address,
|
||||
const accept_handler& handler)
|
||||
{
|
||||
service_.async_accept(impl_, peer_socket.lowest_layer(), peer_address,
|
||||
handler, completion_context::null());
|
||||
}
|
||||
|
||||
/// Start an asynchronous accept. The peer_socket and peer_address objects
|
||||
/// must be valid until the accept's completion handler is invoked.
|
||||
template <typename Stream>
|
||||
void async_accept(Stream& peer_socket, socket_address& peer_address,
|
||||
const accept_handler& handler, completion_context& context)
|
||||
{
|
||||
service_.async_accept(impl_, peer_socket.lowest_layer(), peer_address,
|
||||
handler, context);
|
||||
}
|
||||
|
||||
private:
|
||||
/// The backend service implementation.
|
||||
service_type& service_;
|
||||
|
||||
/// The underlying native implementation.
|
||||
impl_type impl_;
|
||||
};
|
||||
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_BASIC_SOCKET_ACCEPTOR_HPP
|
122
asio/src/asio/basic_socket_connector.hpp
Normal file
122
asio/src/asio/basic_socket_connector.hpp
Normal file
@ -0,0 +1,122 @@
|
||||
//
|
||||
// basic_socket_connector.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_SOCKET_CONNECTOR_HPP
|
||||
#define ASIO_BASIC_SOCKET_CONNECTOR_HPP
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/completion_context.hpp"
|
||||
#include "asio/demuxer.hpp"
|
||||
|
||||
namespace asio {
|
||||
|
||||
class socket_address;
|
||||
|
||||
/// The basic_socket_connector class template is used to connect a socket to a
|
||||
/// remote endpoint. Most applications will simply use the socket_connector
|
||||
/// typedef.
|
||||
template <typename Service>
|
||||
class basic_socket_connector
|
||||
: private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
/// The type of the service that will be used to provide connect operations.
|
||||
typedef Service service_type;
|
||||
|
||||
/// The native implementation type of the socket connector.
|
||||
typedef typename service_type::impl_type impl_type;
|
||||
|
||||
/// Constructor a connector. The connector is automatically opened.
|
||||
explicit basic_socket_connector(demuxer& d)
|
||||
: service_(dynamic_cast<service_type&>(d.get_service(service_type::id))),
|
||||
impl_(service_type::invalid_impl)
|
||||
{
|
||||
service_.create(impl_);
|
||||
}
|
||||
|
||||
/// Destructor.
|
||||
~basic_socket_connector()
|
||||
{
|
||||
service_.destroy(impl_);
|
||||
}
|
||||
|
||||
/// Open the connector.
|
||||
void open()
|
||||
{
|
||||
service_.create(impl_);
|
||||
}
|
||||
|
||||
/// Close the connector.
|
||||
void close()
|
||||
{
|
||||
service_.destroy(impl_);
|
||||
}
|
||||
|
||||
/// Get the underlying implementation in the native type.
|
||||
impl_type impl() const
|
||||
{
|
||||
return impl_;
|
||||
}
|
||||
|
||||
/// Connect the given socket to the peer at the specified address. Throws a
|
||||
/// socket_error exception on failure.
|
||||
template <typename Stream>
|
||||
void connect(Stream& peer_socket, const socket_address& peer_address)
|
||||
{
|
||||
service_.connect(impl_, peer_socket.lowest_layer(), peer_address);
|
||||
}
|
||||
|
||||
/// The type of a handler called when the asynchronous connect completes. The
|
||||
/// only argument is the error code.
|
||||
typedef typename service_type::connect_handler connect_handler;
|
||||
|
||||
/// Start an asynchronous connect. The peer_socket object must be valid until
|
||||
/// the connect's completion handler is invoked.
|
||||
template <typename Stream>
|
||||
void async_connect(Stream& peer_socket,
|
||||
const socket_address& peer_address, const connect_handler& handler)
|
||||
{
|
||||
service_.async_connect(impl_, peer_socket.lowest_layer(), peer_address,
|
||||
handler, completion_context::null());
|
||||
}
|
||||
|
||||
/// Start an asynchronous connect. The peer_socket object must be valid until
|
||||
/// the connect's completion handler is invoked.
|
||||
template <typename Stream>
|
||||
void async_connect(Stream& peer_socket,
|
||||
const socket_address& peer_address, const connect_handler& handler,
|
||||
completion_context& context)
|
||||
{
|
||||
service_.async_connect(impl_, peer_socket.lowest_layer(), peer_address,
|
||||
handler, context);
|
||||
}
|
||||
|
||||
private:
|
||||
/// The backend service implementation.
|
||||
service_type& service_;
|
||||
|
||||
/// The underlying native implementation.
|
||||
impl_type impl_;
|
||||
};
|
||||
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_BASIC_SOCKET_CONNECTOR_HPP
|
185
asio/src/asio/basic_stream_socket.hpp
Normal file
185
asio/src/asio/basic_stream_socket.hpp
Normal file
@ -0,0 +1,185 @@
|
||||
//
|
||||
// basic_stream_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_STREAM_SOCKET_HPP
|
||||
#define ASIO_BASIC_STREAM_SOCKET_HPP
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/completion_context.hpp"
|
||||
#include "asio/demuxer.hpp"
|
||||
|
||||
namespace asio {
|
||||
|
||||
/// The basic_stream_socket class template provides asynchronous and blocking
|
||||
/// stream-oriented socket functionality. Most applications will simply use the
|
||||
/// stream_socket typedef.
|
||||
template <typename Service>
|
||||
class basic_stream_socket
|
||||
: private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
/// The type of the service that will be used to provide socket operations.
|
||||
typedef Service service_type;
|
||||
|
||||
/// The native implementation type of the stream socket.
|
||||
typedef typename service_type::impl_type impl_type;
|
||||
|
||||
/// A basic_stream_socket is always the lowest layer.
|
||||
typedef basic_stream_socket<service_type> lowest_layer_type;
|
||||
|
||||
/// Construct a basic_stream_socket without opening it. The socket needs to
|
||||
/// be connected or accepted before data can be sent or received on it.
|
||||
explicit basic_stream_socket(demuxer& d)
|
||||
: service_(dynamic_cast<service_type&>(d.get_service(service_type::id))),
|
||||
impl_(service_type::invalid_impl)
|
||||
{
|
||||
}
|
||||
|
||||
/// Destructor.
|
||||
~basic_stream_socket()
|
||||
{
|
||||
service_.destroy(impl_);
|
||||
}
|
||||
|
||||
/// Close the socket.
|
||||
void close()
|
||||
{
|
||||
service_.destroy(impl_);
|
||||
}
|
||||
|
||||
/// Get a reference to the lowest layer.
|
||||
lowest_layer_type& lowest_layer()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Get the underlying implementation in the native type.
|
||||
impl_type impl() const
|
||||
{
|
||||
return impl_;
|
||||
}
|
||||
|
||||
/// Set the underlying implementation in the native type. The object must not
|
||||
/// be open priot to this call being made.
|
||||
void set_impl(impl_type new_impl)
|
||||
{
|
||||
service_.create(impl_, new_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.
|
||||
size_t send(const void* data, size_t length)
|
||||
{
|
||||
return service_.send(impl_, data, length);
|
||||
}
|
||||
|
||||
/// The handler when a send operation is completed. The first argument is the
|
||||
/// error code, the second is the number of bytes sent.
|
||||
typedef typename service_type::send_handler send_handler;
|
||||
|
||||
/// Start an asynchronous send. The data being sent must be valid for the
|
||||
/// lifetime of the asynchronous operation.
|
||||
void async_send(const void* data, size_t length,
|
||||
const send_handler& handler,
|
||||
completion_context& context = completion_context::null())
|
||||
{
|
||||
service_.async_send(impl_, length, handler, context);
|
||||
}
|
||||
|
||||
/// Send all of the given data to the peer before returning. Returns the
|
||||
/// number of bytes sent on the last send or 0 if the connection was closed
|
||||
/// cleanly. Throws a socket_error exception on failure.
|
||||
size_t send_n(const void* data, size_t length, size_t* total_bytes_sent = 0)
|
||||
{
|
||||
return service_.send_n(impl_, data, length, total_bytes_sent);
|
||||
}
|
||||
|
||||
/// The handler when a send_n operation is completed. The first argument is
|
||||
/// the error code, the second is the total number of bytes sent, and the
|
||||
/// third is the number of bytes sent in the last send operation.
|
||||
typedef typename service_type::send_n_handler send_n_handler;
|
||||
|
||||
/// 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.
|
||||
void async_send_n(const void* data, size_t length,
|
||||
const send_n_handler& handler,
|
||||
completion_context& context = completion_context::null())
|
||||
{
|
||||
service_.async_send_n(impl_, data, length, handler, context);
|
||||
}
|
||||
|
||||
/// Receive some data from the peer. Returns the number of bytes received or
|
||||
/// 0 if the connection was closed cleanly. Throws a socket_error exception
|
||||
/// on failure.
|
||||
size_t recv(void* data, size_t max_length)
|
||||
{
|
||||
return service_.recv(impl_, data, max_length);
|
||||
}
|
||||
|
||||
/// The handler when a recv operation is completed. The first argument is the
|
||||
/// error code, the second is the number of bytes received.
|
||||
typedef typename service_type::recv_handler recv_handler;
|
||||
|
||||
/// Start an asynchronous receive. The buffer for the data being received must
|
||||
/// be valid for the lifetime of the asynchronous operation.
|
||||
void async_recv(void* data, size_t max_length,
|
||||
const recv_handler& handler,
|
||||
completion_context& context = completion_context::null())
|
||||
{
|
||||
service_.async_recv(impl_, data, max_length, handler, context);
|
||||
}
|
||||
|
||||
/// Receive the specified amount of data from the peer. Returns the number of
|
||||
/// bytes received on the last recv call or 0 if the connection
|
||||
/// was closed cleanly. Throws a socket_error exception on failure.
|
||||
size_t recv_n(void* data, size_t length, size_t* total_bytes_recvd = 0)
|
||||
{
|
||||
return service_.recv_n(impl_, data, length, total_bytes_recvd);
|
||||
}
|
||||
|
||||
/// The handler when a recv_n operation is completed. The first argument is
|
||||
/// the error code, the second is the number of bytes received, the third is
|
||||
/// the number of bytes received in the last recv operation.
|
||||
typedef typename service_type::recv_n_handler recv_n_handler;
|
||||
|
||||
/// 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.
|
||||
void async_recv_n(void* data, size_t length, const recv_n_handler& handler,
|
||||
completion_context& context = completion_context::null())
|
||||
{
|
||||
service_.async_recv_n(impl_, data, length, handler, context);
|
||||
}
|
||||
|
||||
private:
|
||||
/// The backend service implementation.
|
||||
service_type& service_;
|
||||
|
||||
/// The underlying native implementation.
|
||||
impl_type impl_;
|
||||
};
|
||||
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_BASIC_STREAM_SOCKET_HPP
|
@ -35,14 +35,17 @@ class basic_timer_queue
|
||||
: private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
/// The type of the service that will be used to provide timer operations.
|
||||
typedef Service service_type;
|
||||
|
||||
/// Constructor.
|
||||
explicit basic_timer_queue(demuxer& d)
|
||||
: service_(dynamic_cast<Service&>(d.get_service(Service::id)))
|
||||
: service_(dynamic_cast<service_type&>(d.get_service(service_type::id)))
|
||||
{
|
||||
}
|
||||
|
||||
/// The handler for when a timer expires.
|
||||
typedef typename Service::timer_handler timer_handler;
|
||||
typedef typename service_type::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.
|
||||
@ -72,7 +75,7 @@ public:
|
||||
|
||||
private:
|
||||
/// The backend service implementation.
|
||||
Service& service_;
|
||||
service_type& service_;
|
||||
};
|
||||
|
||||
} // namespace asio
|
||||
|
@ -27,14 +27,7 @@ namespace asio {
|
||||
namespace detail {
|
||||
|
||||
const service_type_id dgram_socket_service::id;
|
||||
|
||||
void
|
||||
dgram_socket_service::
|
||||
nullify(
|
||||
impl_type& impl)
|
||||
{
|
||||
impl = invalid_socket;
|
||||
}
|
||||
const dgram_socket_service::impl_type dgram_socket_service::invalid_impl;
|
||||
|
||||
void
|
||||
dgram_socket_service::
|
||||
@ -58,14 +51,6 @@ create(
|
||||
impl = sock.release();
|
||||
}
|
||||
|
||||
void
|
||||
attach(
|
||||
impl_type& impl,
|
||||
impl_type new_impl)
|
||||
{
|
||||
impl = new_impl;
|
||||
}
|
||||
|
||||
void
|
||||
dgram_socket_service::
|
||||
destroy(
|
||||
|
@ -21,11 +21,11 @@
|
||||
#include <boost/function.hpp>
|
||||
#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 completion_context; }
|
||||
namespace asio { class socket_address; }
|
||||
namespace asio { class socket_error; }
|
||||
|
||||
@ -39,29 +39,26 @@ 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.
|
||||
// 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);
|
||||
// The value to use for uninitialised implementations.
|
||||
static const impl_type invalid_impl = invalid_socket;
|
||||
|
||||
// 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.
|
||||
// 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.
|
||||
// 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<void, const socket_error&, size_t> sendto_handler;
|
||||
|
||||
// Start an asynchronous send. The data being sent must be valid for the
|
||||
@ -70,13 +67,13 @@ public:
|
||||
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.
|
||||
// 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.
|
||||
// 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<void, const socket_error&, size_t> recvfrom_handler;
|
||||
|
||||
// Start an asynchronous receive. The buffer for the data being received and
|
||||
|
@ -60,11 +60,11 @@ select_provider::
|
||||
do_dgram_socket_destroy(
|
||||
dgram_socket_service::impl_type& impl)
|
||||
{
|
||||
if (impl != invalid_socket)
|
||||
if (impl != dgram_socket_service::invalid_impl)
|
||||
{
|
||||
selector_.close_descriptor(impl);
|
||||
socket_ops::close(impl);
|
||||
impl = invalid_socket;
|
||||
impl = dgram_socket_service::invalid_impl;
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,19 +199,15 @@ do_dgram_socket_async_recvfrom(
|
||||
|
||||
void
|
||||
select_provider::
|
||||
register_socket_acceptor(
|
||||
socket_acceptor&)
|
||||
do_socket_acceptor_destroy(
|
||||
socket_acceptor_service::impl_type& impl)
|
||||
{
|
||||
// Registration is not required with the select_provider since each operation
|
||||
// is handled individually.
|
||||
}
|
||||
|
||||
void
|
||||
select_provider::
|
||||
deregister_socket_acceptor(
|
||||
socket_acceptor& socket)
|
||||
{
|
||||
selector_.close_descriptor(socket.native_handle());
|
||||
if (impl != socket_acceptor_service::invalid_impl)
|
||||
{
|
||||
selector_.close_descriptor(impl);
|
||||
socket_ops::close(impl);
|
||||
impl = socket_acceptor_service::invalid_impl;
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
@ -219,9 +215,8 @@ namespace
|
||||
struct accept_op : public select_op
|
||||
{
|
||||
demuxer* demuxer_;
|
||||
socket_acceptor* acceptor_;
|
||||
stream_socket* peer_socket_;
|
||||
socket_acceptor::accept_handler handler_;
|
||||
socket_acceptor_service::peer_type* peer_socket_;
|
||||
socket_acceptor_service::accept_handler handler_;
|
||||
completion_context* context_;
|
||||
|
||||
accept_op(int d) : select_op(d) {}
|
||||
@ -231,8 +226,7 @@ namespace
|
||||
socket_type new_socket = socket_ops::accept(descriptor(), 0, 0);
|
||||
socket_error error(new_socket == invalid_socket
|
||||
? socket_ops::get_error() : socket_error::success);
|
||||
select_provider::do_associate_accepted_stream_socket(*acceptor_,
|
||||
*peer_socket_, new_socket);
|
||||
peer_socket_->set_impl(new_socket);
|
||||
demuxer_->operation_completed(boost::bind(&accept_op::do_upcall,
|
||||
handler_, error), *context_);
|
||||
delete this;
|
||||
@ -246,7 +240,8 @@ namespace
|
||||
delete this;
|
||||
}
|
||||
|
||||
static void do_upcall(const socket_acceptor::accept_handler& handler,
|
||||
static void do_upcall(
|
||||
const socket_acceptor_service::accept_handler& handler,
|
||||
const socket_error& error)
|
||||
{
|
||||
handler(error);
|
||||
@ -256,13 +251,13 @@ namespace
|
||||
|
||||
void
|
||||
select_provider::
|
||||
async_socket_accept(
|
||||
socket_acceptor& acceptor,
|
||||
stream_socket& peer_socket,
|
||||
do_socket_acceptor_async_accept(
|
||||
socket_acceptor_service::impl_type& impl,
|
||||
socket_acceptor_service::peer_type& peer_socket,
|
||||
const accept_handler& handler,
|
||||
completion_context& context)
|
||||
{
|
||||
if (peer_socket.native_handle() != invalid_socket)
|
||||
if (peer_socket.impl() != invalid_socket)
|
||||
{
|
||||
socket_error error(socket_error::already_connected);
|
||||
demuxer_.operation_immediate(
|
||||
@ -270,9 +265,8 @@ async_socket_accept(
|
||||
return;
|
||||
}
|
||||
|
||||
accept_op* op = new accept_op(acceptor.native_handle());
|
||||
accept_op* op = new accept_op(impl);
|
||||
op->demuxer_ = &demuxer_;
|
||||
op->acceptor_ = &acceptor;
|
||||
op->peer_socket_ = &peer_socket;
|
||||
op->handler_ = handler;
|
||||
op->context_ = &context;
|
||||
@ -287,10 +281,9 @@ namespace
|
||||
struct accept_with_addr_op : public select_op
|
||||
{
|
||||
demuxer* demuxer_;
|
||||
socket_acceptor* acceptor_;
|
||||
stream_socket* peer_socket_;
|
||||
socket_acceptor_service::peer_type* peer_socket_;
|
||||
socket_address* peer_address_;
|
||||
socket_acceptor::accept_handler handler_;
|
||||
socket_acceptor_service::accept_handler handler_;
|
||||
completion_context* context_;
|
||||
|
||||
accept_with_addr_op(int d) : select_op(d) {}
|
||||
@ -303,8 +296,7 @@ namespace
|
||||
socket_error error(new_socket == invalid_socket
|
||||
? socket_ops::get_error() : socket_error::success);
|
||||
peer_address_->native_size(addr_len);
|
||||
select_provider::do_associate_accepted_stream_socket(*acceptor_,
|
||||
*peer_socket_, new_socket);
|
||||
peer_socket_->set_impl(new_socket);
|
||||
demuxer_->operation_completed(boost::bind(&accept_op::do_upcall,
|
||||
handler_, error), *context_);
|
||||
delete this;
|
||||
@ -318,7 +310,8 @@ namespace
|
||||
delete this;
|
||||
}
|
||||
|
||||
static void do_upcall(const socket_acceptor::accept_handler& handler,
|
||||
static void do_upcall(
|
||||
const socket_acceptor_service::accept_handler& handler,
|
||||
const socket_error& error)
|
||||
{
|
||||
handler(error);
|
||||
@ -328,14 +321,14 @@ namespace
|
||||
|
||||
void
|
||||
select_provider::
|
||||
async_socket_accept(
|
||||
socket_acceptor& acceptor,
|
||||
stream_socket& peer_socket,
|
||||
do_socket_acceptor_async_accept(
|
||||
socket_acceptor_service::impl_type& impl,
|
||||
socket_acceptor_service::peer_type& peer_socket,
|
||||
socket_address& peer_address,
|
||||
const accept_handler& handler,
|
||||
completion_context& context)
|
||||
{
|
||||
if (peer_socket.native_handle() != invalid_socket)
|
||||
if (peer_socket.impl() != invalid_socket)
|
||||
{
|
||||
socket_error error(socket_error::already_connected);
|
||||
demuxer_.operation_immediate(
|
||||
@ -343,9 +336,8 @@ async_socket_accept(
|
||||
return;
|
||||
}
|
||||
|
||||
accept_with_addr_op* op = new accept_with_addr_op(acceptor.native_handle());
|
||||
accept_with_addr_op* op = new accept_with_addr_op(impl);
|
||||
op->demuxer_ = &demuxer_;
|
||||
op->acceptor_ = &acceptor;
|
||||
op->peer_socket_ = &peer_socket;
|
||||
op->peer_address_ = &peer_address;
|
||||
op->handler_ = handler;
|
||||
@ -358,33 +350,20 @@ async_socket_accept(
|
||||
|
||||
void
|
||||
select_provider::
|
||||
do_associate_accepted_stream_socket(
|
||||
socket_acceptor& acceptor,
|
||||
stream_socket& peer_socket,
|
||||
stream_socket::native_type handle)
|
||||
do_socket_connector_destroy(
|
||||
socket_connector_service::impl_type& impl)
|
||||
{
|
||||
associate_accepted_stream_socket(acceptor, peer_socket, handle);
|
||||
}
|
||||
if (impl != socket_connector_service::invalid_impl)
|
||||
{
|
||||
socket_connector_impl::socket_set sockets;
|
||||
impl->get_sockets(sockets);
|
||||
socket_connector_impl::socket_set::iterator i = sockets.begin();
|
||||
while (i != sockets.end())
|
||||
selector_.close_descriptor(*i++);
|
||||
|
||||
void
|
||||
select_provider::
|
||||
register_socket_connector(
|
||||
socket_connector&)
|
||||
{
|
||||
// Registration is not required with the select_provider since each operation
|
||||
// is handled individually.
|
||||
}
|
||||
|
||||
void
|
||||
select_provider::
|
||||
deregister_socket_connector(
|
||||
socket_connector& connector)
|
||||
{
|
||||
socket_connector_impl::socket_set sockets;
|
||||
connector.native_handle()->get_sockets(sockets);
|
||||
socket_connector_impl::socket_set::iterator i = sockets.begin();
|
||||
while (i != sockets.end())
|
||||
selector_.close_descriptor(*i++);
|
||||
delete impl;
|
||||
impl = socket_connector_service::invalid_impl;
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
@ -392,10 +371,10 @@ namespace
|
||||
struct connect_op : public select_op
|
||||
{
|
||||
demuxer* demuxer_;
|
||||
socket_connector* connector_;
|
||||
stream_socket* peer_socket_;
|
||||
socket_connector_service::impl_type connector_impl_;
|
||||
socket_connector_service::peer_type* peer_socket_;
|
||||
generic_address peer_address_;
|
||||
socket_connector::connect_handler handler_;
|
||||
socket_connector_service::connect_handler handler_;
|
||||
completion_context* context_;
|
||||
|
||||
connect_op(int d) : select_op(d) {}
|
||||
@ -403,7 +382,7 @@ namespace
|
||||
virtual void do_operation()
|
||||
{
|
||||
socket_holder new_socket(descriptor());
|
||||
connector_->native_handle()->remove_socket(new_socket.get());
|
||||
connector_impl_->remove_socket(new_socket.get());
|
||||
|
||||
// Get the error code from the connect operation.
|
||||
int connect_error = 0;
|
||||
@ -412,8 +391,6 @@ namespace
|
||||
&connect_error, &connect_error_len) == socket_error_retval)
|
||||
{
|
||||
socket_error error(socket_ops::get_error());
|
||||
select_provider::do_associate_connected_stream_socket(*connector_,
|
||||
*peer_socket_, invalid_socket);
|
||||
demuxer_->operation_completed(boost::bind(&connect_op::do_upcall,
|
||||
handler_, error), *context_);
|
||||
delete this;
|
||||
@ -424,8 +401,6 @@ namespace
|
||||
if (connect_error)
|
||||
{
|
||||
socket_error error(connect_error);
|
||||
select_provider::do_associate_connected_stream_socket(*connector_,
|
||||
*peer_socket_, invalid_socket);
|
||||
demuxer_->operation_completed(boost::bind(&connect_op::do_upcall,
|
||||
handler_, error), *context_);
|
||||
delete this;
|
||||
@ -437,8 +412,6 @@ namespace
|
||||
if (socket_ops::ioctl(new_socket.get(), FIONBIO, &non_blocking))
|
||||
{
|
||||
socket_error error(socket_ops::get_error());
|
||||
select_provider::do_associate_connected_stream_socket(*connector_,
|
||||
*peer_socket_, invalid_socket);
|
||||
demuxer_->operation_completed(boost::bind(&connect_op::do_upcall,
|
||||
handler_, error), *context_);
|
||||
delete this;
|
||||
@ -446,8 +419,7 @@ namespace
|
||||
}
|
||||
|
||||
// Post the result of the successful connection operation.
|
||||
select_provider::do_associate_connected_stream_socket(*connector_,
|
||||
*peer_socket_, new_socket.release());
|
||||
peer_socket_->set_impl(new_socket.release());
|
||||
socket_error error(socket_error::success);
|
||||
demuxer_->operation_completed(boost::bind(&connect_op::do_upcall,
|
||||
handler_, error), *context_);
|
||||
@ -456,14 +428,15 @@ namespace
|
||||
|
||||
virtual void do_cancel()
|
||||
{
|
||||
connector_->native_handle()->remove_socket(descriptor());
|
||||
connector_impl_->remove_socket(descriptor());
|
||||
socket_error error(socket_error::operation_aborted);
|
||||
demuxer_->operation_completed(boost::bind(&connect_op::do_upcall,
|
||||
handler_, error), *context_);
|
||||
delete this;
|
||||
}
|
||||
|
||||
static void do_upcall(const socket_connector::connect_handler& handler,
|
||||
static void do_upcall(
|
||||
const socket_connector_service::connect_handler& handler,
|
||||
const socket_error& error)
|
||||
{
|
||||
handler(error);
|
||||
@ -473,14 +446,13 @@ namespace
|
||||
|
||||
void
|
||||
select_provider::
|
||||
async_socket_connect(
|
||||
socket_connector& connector,
|
||||
stream_socket& peer_socket,
|
||||
const socket_address& peer_address,
|
||||
const connect_handler& handler,
|
||||
do_socket_connector_async_connect(
|
||||
socket_connector_service::impl_type& impl,
|
||||
socket_connector_service::peer_type& peer_socket,
|
||||
const socket_address& peer_address, const connect_handler& handler,
|
||||
completion_context& context)
|
||||
{
|
||||
if (peer_socket.native_handle() != invalid_socket)
|
||||
if (peer_socket.impl() != invalid_socket)
|
||||
{
|
||||
socket_error error(socket_error::already_connected);
|
||||
demuxer_.operation_immediate(
|
||||
@ -495,7 +467,6 @@ async_socket_connect(
|
||||
if (new_socket.get() == invalid_socket)
|
||||
{
|
||||
socket_error error(socket_ops::get_error());
|
||||
associate_connected_stream_socket(connector, peer_socket, invalid_socket);
|
||||
demuxer_.operation_immediate(boost::bind(&connect_op::do_upcall, handler,
|
||||
error), context);
|
||||
return;
|
||||
@ -507,7 +478,6 @@ async_socket_connect(
|
||||
if (socket_ops::ioctl(new_socket.get(), FIONBIO, &non_blocking))
|
||||
{
|
||||
socket_error error(socket_ops::get_error());
|
||||
associate_connected_stream_socket(connector, peer_socket, invalid_socket);
|
||||
demuxer_.operation_immediate(boost::bind(&connect_op::do_upcall, handler,
|
||||
error), context);
|
||||
return;
|
||||
@ -519,8 +489,7 @@ async_socket_connect(
|
||||
{
|
||||
// The connect operation has finished successfully so we need to post the
|
||||
// completion immediately.
|
||||
associate_connected_stream_socket(connector, peer_socket,
|
||||
new_socket.release());
|
||||
peer_socket.set_impl(new_socket.release());
|
||||
socket_error error(socket_error::success);
|
||||
demuxer_.operation_immediate(boost::bind(&connect_op::do_upcall, handler,
|
||||
error), context);
|
||||
@ -533,13 +502,13 @@ async_socket_connect(
|
||||
|
||||
connect_op* op = new connect_op(new_socket.get());
|
||||
op->demuxer_ = &demuxer_;
|
||||
op->connector_ = &connector;
|
||||
op->connector_impl_ = impl;
|
||||
op->peer_socket_ = &peer_socket;
|
||||
op->peer_address_ = peer_address;
|
||||
op->handler_ = handler;
|
||||
op->context_ = &context;
|
||||
|
||||
connector.native_handle()->add_socket(new_socket.get());
|
||||
impl->add_socket(new_socket.get());
|
||||
new_socket.release();
|
||||
|
||||
demuxer_.operation_started();
|
||||
@ -550,7 +519,6 @@ async_socket_connect(
|
||||
{
|
||||
// The connect operation has failed, so post completion immediately.
|
||||
socket_error error(socket_ops::get_error());
|
||||
associate_connected_stream_socket(connector, peer_socket, invalid_socket);
|
||||
demuxer_.operation_immediate(boost::bind(&connect_op::do_upcall, handler,
|
||||
error), context);
|
||||
}
|
||||
@ -558,29 +526,24 @@ async_socket_connect(
|
||||
|
||||
void
|
||||
select_provider::
|
||||
do_associate_connected_stream_socket(
|
||||
socket_connector& connector,
|
||||
stream_socket& peer_socket,
|
||||
stream_socket::native_type handle)
|
||||
do_stream_socket_create(
|
||||
stream_socket_service::impl_type& impl,
|
||||
stream_socket_service::impl_type new_impl)
|
||||
{
|
||||
associate_connected_stream_socket(connector, peer_socket, handle);
|
||||
impl = new_impl;
|
||||
}
|
||||
|
||||
void
|
||||
select_provider::
|
||||
register_stream_socket(
|
||||
stream_socket&)
|
||||
do_stream_socket_destroy(
|
||||
stream_socket_service::impl_type& impl)
|
||||
{
|
||||
// Registration is not required with the select_provider since each operation
|
||||
// is handled individually.
|
||||
}
|
||||
|
||||
void
|
||||
select_provider::
|
||||
deregister_stream_socket(
|
||||
stream_socket& socket)
|
||||
{
|
||||
selector_.close_descriptor(socket.native_handle());
|
||||
if (impl != stream_socket_service::invalid_impl)
|
||||
{
|
||||
selector_.close_descriptor(impl);
|
||||
socket_ops::close(impl);
|
||||
impl = stream_socket_service::invalid_impl;
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
@ -590,7 +553,7 @@ namespace
|
||||
demuxer* demuxer_;
|
||||
const void* data_;
|
||||
size_t length_;
|
||||
stream_socket::send_handler handler_;
|
||||
stream_socket_service::send_handler handler_;
|
||||
completion_context* context_;
|
||||
|
||||
send_op(int d) : select_op(d) {}
|
||||
@ -613,7 +576,7 @@ namespace
|
||||
delete this;
|
||||
}
|
||||
|
||||
static void do_upcall(const stream_socket::send_handler& handler,
|
||||
static void do_upcall(const stream_socket_service::send_handler& handler,
|
||||
const socket_error& error, size_t bytes_transferred)
|
||||
{
|
||||
handler(error, bytes_transferred);
|
||||
@ -623,14 +586,14 @@ namespace
|
||||
|
||||
void
|
||||
select_provider::
|
||||
async_stream_socket_send(
|
||||
stream_socket& socket,
|
||||
do_stream_socket_async_send(
|
||||
stream_socket_service::impl_type& impl,
|
||||
const void* data,
|
||||
size_t length,
|
||||
const send_handler& handler,
|
||||
completion_context& context)
|
||||
{
|
||||
send_op* op = new send_op(socket.native_handle());
|
||||
send_op* op = new send_op(impl);
|
||||
op->demuxer_ = &demuxer_;
|
||||
op->data_ = data;
|
||||
op->length_ = length;
|
||||
@ -651,7 +614,7 @@ namespace
|
||||
const void* data_;
|
||||
size_t length_;
|
||||
size_t already_sent_;
|
||||
stream_socket::send_n_handler handler_;
|
||||
stream_socket_service::send_n_handler handler_;
|
||||
completion_context* context_;
|
||||
|
||||
send_n_op(int d) : select_op(d) {}
|
||||
@ -686,7 +649,7 @@ namespace
|
||||
delete this;
|
||||
}
|
||||
|
||||
static void do_upcall(const stream_socket::send_n_handler& handler,
|
||||
static void do_upcall(const stream_socket_service::send_n_handler& handler,
|
||||
const socket_error& error, size_t total_bytes_transferred,
|
||||
size_t last_bytes_transferred)
|
||||
{
|
||||
@ -697,14 +660,14 @@ namespace
|
||||
|
||||
void
|
||||
select_provider::
|
||||
async_stream_socket_send_n(
|
||||
stream_socket& socket,
|
||||
do_stream_socket_async_send_n(
|
||||
stream_socket_service::impl_type& impl,
|
||||
const void* data,
|
||||
size_t length,
|
||||
const send_n_handler& handler,
|
||||
completion_context& context)
|
||||
{
|
||||
send_n_op* op = new send_n_op(socket.native_handle());
|
||||
send_n_op* op = new send_n_op(impl);
|
||||
op->demuxer_ = &demuxer_;
|
||||
op->selector_ = &selector_;
|
||||
op->data_ = data;
|
||||
@ -725,7 +688,7 @@ namespace
|
||||
demuxer* demuxer_;
|
||||
void* data_;
|
||||
size_t max_length_;
|
||||
stream_socket::recv_handler handler_;
|
||||
stream_socket_service::recv_handler handler_;
|
||||
completion_context* context_;
|
||||
|
||||
recv_op(int d) : select_op(d) {}
|
||||
@ -748,7 +711,7 @@ namespace
|
||||
delete this;
|
||||
}
|
||||
|
||||
static void do_upcall(const stream_socket::recv_handler& handler,
|
||||
static void do_upcall(const stream_socket_service::recv_handler& handler,
|
||||
const socket_error& error, size_t bytes_transferred)
|
||||
{
|
||||
handler(error, bytes_transferred);
|
||||
@ -758,14 +721,14 @@ namespace
|
||||
|
||||
void
|
||||
select_provider::
|
||||
async_stream_socket_recv(
|
||||
stream_socket& socket,
|
||||
do_stream_socket_async_recv(
|
||||
stream_socket_service::impl_type& impl,
|
||||
void* data,
|
||||
size_t max_length,
|
||||
const recv_handler& handler,
|
||||
completion_context& context)
|
||||
{
|
||||
recv_op* op = new recv_op(socket.native_handle());
|
||||
recv_op* op = new recv_op(impl);
|
||||
op->demuxer_ = &demuxer_;
|
||||
op->data_ = data;
|
||||
op->max_length_ = max_length;
|
||||
@ -786,7 +749,7 @@ namespace
|
||||
void* data_;
|
||||
size_t length_;
|
||||
size_t already_recvd_;
|
||||
stream_socket::recv_n_handler handler_;
|
||||
stream_socket_service::recv_n_handler handler_;
|
||||
completion_context* context_;
|
||||
|
||||
recv_n_op(int d) : select_op(d) {}
|
||||
@ -821,7 +784,7 @@ namespace
|
||||
delete this;
|
||||
}
|
||||
|
||||
static void do_upcall(const stream_socket::recv_n_handler& handler,
|
||||
static void do_upcall(const stream_socket_service::recv_n_handler& handler,
|
||||
const socket_error& error, size_t total_bytes_transferred,
|
||||
size_t last_bytes_transferred)
|
||||
{
|
||||
@ -832,14 +795,14 @@ namespace
|
||||
|
||||
void
|
||||
select_provider::
|
||||
async_stream_socket_recv_n(
|
||||
stream_socket& socket,
|
||||
do_stream_socket_async_recv_n(
|
||||
stream_socket_service::impl_type& impl,
|
||||
void* data,
|
||||
size_t length,
|
||||
const recv_n_handler& handler,
|
||||
completion_context& context)
|
||||
{
|
||||
recv_n_op* op = new recv_n_op(socket.native_handle());
|
||||
recv_n_op* op = new recv_n_op(impl);
|
||||
op->demuxer_ = &demuxer_;
|
||||
op->selector_ = &selector_;
|
||||
op->data_ = data;
|
||||
|
@ -59,82 +59,66 @@ public:
|
||||
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.
|
||||
virtual void register_socket_acceptor(socket_acceptor& acceptor);
|
||||
|
||||
// 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);
|
||||
// Destroy a socket connector implementation.
|
||||
virtual void do_socket_acceptor_destroy(
|
||||
socket_acceptor_service::impl_type& impl);
|
||||
|
||||
// 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);
|
||||
virtual void do_socket_acceptor_async_accept(
|
||||
socket_acceptor_service::impl_type& impl,
|
||||
socket_acceptor_service::peer_type& peer_socket,
|
||||
const accept_handler& handler, completion_context& context);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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,
|
||||
virtual void do_socket_acceptor_async_accept(
|
||||
socket_acceptor_service::impl_type& impl,
|
||||
socket_acceptor_service::peer_type& peer_socket,
|
||||
socket_address& peer_address, const accept_handler& handler,
|
||||
completion_context& context);
|
||||
|
||||
// Destroy a socket connector implementation.
|
||||
virtual void do_socket_connector_destroy(
|
||||
socket_connector_service::impl_type& impl);
|
||||
|
||||
// Start an asynchronous connect.
|
||||
virtual void do_socket_connector_async_connect(
|
||||
socket_connector_service::impl_type& impl,
|
||||
socket_connector_service::peer_type& peer_socket,
|
||||
const socket_address& peer_address, const connect_handler& handler,
|
||||
completion_context& context);
|
||||
|
||||
// Create a new socket connector implementation.
|
||||
virtual void do_stream_socket_create(stream_socket_service::impl_type& impl,
|
||||
stream_socket_service::impl_type new_impl);
|
||||
|
||||
// Destroy a socket connector implementation.
|
||||
virtual void do_stream_socket_destroy(
|
||||
stream_socket_service::impl_type& impl);
|
||||
|
||||
// Start an asynchronous send.
|
||||
virtual void do_stream_socket_async_send(
|
||||
stream_socket_service::impl_type& impl, const void* data, size_t length,
|
||||
const send_handler& handler, completion_context& context);
|
||||
|
||||
// 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);
|
||||
// been sent or an error occurs.
|
||||
virtual void do_stream_socket_async_send_n(
|
||||
stream_socket_service::impl_type& impl, const void* data, size_t length,
|
||||
const send_n_handler& handler, completion_context& context);
|
||||
|
||||
// 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);
|
||||
// Start an asynchronous receive.
|
||||
virtual void do_stream_socket_async_recv(
|
||||
stream_socket_service::impl_type& impl, void* data, size_t max_length,
|
||||
const recv_handler& handler, completion_context& context);
|
||||
|
||||
// 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);
|
||||
|
||||
// Provide access to these functions for the operation implementations.
|
||||
static void do_associate_accepted_stream_socket(socket_acceptor& acceptor,
|
||||
stream_socket& peer_socket, stream_socket::native_type handle);
|
||||
static void do_associate_connected_stream_socket(socket_connector& connector,
|
||||
stream_socket& peer_socket, stream_socket::native_type handle);
|
||||
// number of bytes has been received or an error occurs.
|
||||
virtual void do_stream_socket_async_recv_n(
|
||||
stream_socket_service::impl_type& impl, void* data, size_t length,
|
||||
const recv_n_handler& handler, completion_context& context);
|
||||
|
||||
private:
|
||||
// The demuxer used for delivering completion notifications.
|
||||
|
@ -14,19 +14,125 @@
|
||||
|
||||
#include "asio/detail/socket_acceptor_service.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <boost/throw_exception.hpp>
|
||||
#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 socket_acceptor_service::id;
|
||||
|
||||
const socket_acceptor_service::impl_type socket_acceptor_service::invalid_impl;
|
||||
|
||||
void
|
||||
socket_acceptor_service::
|
||||
associate_accepted_stream_socket(
|
||||
socket_acceptor& acceptor,
|
||||
stream_socket& peer_socket,
|
||||
stream_socket::native_type handle)
|
||||
create(
|
||||
impl_type& impl,
|
||||
const socket_address& address)
|
||||
{
|
||||
acceptor.associate(peer_socket, handle);
|
||||
create(impl, address, SOMAXCONN);
|
||||
}
|
||||
|
||||
void
|
||||
socket_acceptor_service::
|
||||
create(
|
||||
impl_type& impl,
|
||||
const socket_address& address,
|
||||
int listen_queue)
|
||||
{
|
||||
socket_holder sock(socket_ops::socket(address.family(), SOCK_STREAM,
|
||||
IPPROTO_TCP));
|
||||
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()));
|
||||
|
||||
if (socket_ops::listen(sock.get(), listen_queue) == socket_error_retval)
|
||||
boost::throw_exception(socket_error(socket_ops::get_error()));
|
||||
|
||||
impl = sock.release();
|
||||
}
|
||||
|
||||
void
|
||||
socket_acceptor_service::
|
||||
destroy(
|
||||
impl_type& impl)
|
||||
{
|
||||
do_socket_acceptor_destroy(impl);
|
||||
}
|
||||
|
||||
void
|
||||
socket_acceptor_service::
|
||||
accept(
|
||||
impl_type& impl,
|
||||
peer_type& peer_socket)
|
||||
{
|
||||
// We cannot accept a socket that is already open.
|
||||
if (peer_socket.impl() != invalid_socket)
|
||||
boost::throw_exception(socket_error(socket_error::already_connected));
|
||||
|
||||
socket_type new_socket = socket_ops::accept(impl, 0, 0);
|
||||
if (int error = socket_ops::get_error())
|
||||
boost::throw_exception(socket_error(error));
|
||||
|
||||
peer_socket.set_impl(new_socket);
|
||||
}
|
||||
|
||||
void
|
||||
socket_acceptor_service::
|
||||
accept(
|
||||
impl_type& impl,
|
||||
peer_type& peer_socket,
|
||||
socket_address& peer_address)
|
||||
{
|
||||
// We cannot accept a socket that is already open.
|
||||
if (peer_socket.impl() != invalid_socket)
|
||||
boost::throw_exception(socket_error(socket_error::already_connected));
|
||||
|
||||
socket_addr_len_type addr_len = peer_address.native_size();
|
||||
socket_type new_socket = socket_ops::accept(impl,
|
||||
peer_address.native_address(), &addr_len);
|
||||
if (int error = socket_ops::get_error())
|
||||
boost::throw_exception(socket_error(error));
|
||||
peer_address.native_size(addr_len);
|
||||
|
||||
peer_socket.set_impl(new_socket);
|
||||
}
|
||||
|
||||
void
|
||||
socket_acceptor_service::
|
||||
async_accept(
|
||||
impl_type& impl,
|
||||
peer_type& peer_socket,
|
||||
const accept_handler& handler,
|
||||
completion_context& context)
|
||||
{
|
||||
do_socket_acceptor_async_accept(impl, peer_socket, handler, context);
|
||||
}
|
||||
|
||||
void
|
||||
socket_acceptor_service::
|
||||
async_accept(
|
||||
impl_type& impl,
|
||||
peer_type& peer_socket,
|
||||
socket_address& peer_address,
|
||||
const accept_handler& handler,
|
||||
completion_context& context)
|
||||
{
|
||||
do_socket_acceptor_async_accept(impl, peer_socket, peer_address, handler,
|
||||
context);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
@ -17,10 +17,19 @@
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <boost/function.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/basic_stream_socket.hpp"
|
||||
#include "asio/service.hpp"
|
||||
#include "asio/service_type_id.hpp"
|
||||
#include "asio/socket_acceptor.hpp"
|
||||
#include "asio/stream_socket.hpp"
|
||||
#include "asio/detail/stream_socket_service.hpp"
|
||||
#include "asio/detail/socket_types.hpp"
|
||||
|
||||
namespace asio { class completion_context; }
|
||||
namespace asio { class socket_address; }
|
||||
namespace asio { class socket_error; }
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
@ -29,37 +38,67 @@ class socket_acceptor_service
|
||||
: public virtual service
|
||||
{
|
||||
public:
|
||||
typedef socket_acceptor::accept_handler accept_handler;
|
||||
|
||||
// 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.
|
||||
virtual void register_socket_acceptor(socket_acceptor& acceptor) = 0;
|
||||
// The native type of the socket acceptor. This type is dependent on the
|
||||
// underlying implementation of the socket layer.
|
||||
typedef socket_type impl_type;
|
||||
|
||||
// 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;
|
||||
// The value to use for uninitialised implementations.
|
||||
static const impl_type invalid_impl = invalid_socket;
|
||||
|
||||
// The type of the stream sockets that will be connected.
|
||||
typedef basic_stream_socket<stream_socket_service> peer_type;
|
||||
|
||||
// Create a new socket connector implementation.
|
||||
void create(impl_type& impl, const socket_address& address);
|
||||
|
||||
// Create a new socket connector implementation.
|
||||
void create(impl_type& impl, const socket_address& address,
|
||||
int listen_queue);
|
||||
|
||||
// Destroy a socket connector implementation.
|
||||
void destroy(impl_type& impl);
|
||||
|
||||
// Accept a new connection. Throws a socket_error exception on failure.
|
||||
void accept(impl_type& impl, peer_type& peer_socket);
|
||||
|
||||
// Accept a new connection. Throws a socket_error exception on failure.
|
||||
void accept(impl_type& impl, peer_type& peer_socket,
|
||||
socket_address& peer_address);
|
||||
|
||||
// The type of a handler called when the asynchronous accept completes. The
|
||||
// only argument is the error code.
|
||||
typedef boost::function1<void, const socket_error&> accept_handler;
|
||||
|
||||
// Start an asynchronous accept. The peer_socket object must be valid until
|
||||
// the accept's completion handler is invoked.
|
||||
void async_accept(impl_type& impl, peer_type& peer_socket,
|
||||
const accept_handler& handler, completion_context& context);
|
||||
|
||||
// Start an asynchronous accept. The peer_socket and peer_address objects
|
||||
// must be valid until the accept's completion handler is invoked.
|
||||
void async_accept(impl_type& impl, peer_type& peer_socket,
|
||||
socket_address& peer_address, const accept_handler& handler,
|
||||
completion_context& context);
|
||||
|
||||
private:
|
||||
// Destroy a socket connector implementation.
|
||||
virtual void do_socket_acceptor_destroy(impl_type& impl) = 0;
|
||||
|
||||
// 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,
|
||||
virtual void do_socket_acceptor_async_accept(impl_type& impl,
|
||||
peer_type& 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.
|
||||
virtual void async_socket_accept(socket_acceptor& acceptor,
|
||||
stream_socket& peer_socket, socket_address& peer_address,
|
||||
virtual void do_socket_acceptor_async_accept(impl_type& impl,
|
||||
peer_type& 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.
|
||||
static void associate_accepted_stream_socket(socket_acceptor& acceptor,
|
||||
stream_socket& peer_socket, stream_socket::native_type handle);
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -14,19 +14,81 @@
|
||||
|
||||
#include "asio/detail/socket_connector_service.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/socket_address.hpp"
|
||||
#include "asio/socket_error.hpp"
|
||||
#include "asio/detail/socket_connector_impl.hpp"
|
||||
#include "asio/detail/socket_holder.hpp"
|
||||
#include "asio/detail/socket_ops.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
const service_type_id socket_connector_service::id;
|
||||
|
||||
const socket_connector_service::impl_type
|
||||
socket_connector_service::invalid_impl;
|
||||
|
||||
void
|
||||
socket_connector_service::
|
||||
associate_connected_stream_socket(
|
||||
socket_connector& connector,
|
||||
stream_socket& peer_socket,
|
||||
stream_socket::native_type handle)
|
||||
create(
|
||||
impl_type& impl)
|
||||
{
|
||||
connector.associate(peer_socket, handle);
|
||||
impl = new socket_connector_impl;
|
||||
}
|
||||
|
||||
void
|
||||
socket_connector_service::
|
||||
destroy(impl_type& impl)
|
||||
{
|
||||
do_socket_connector_destroy(impl);
|
||||
}
|
||||
|
||||
void
|
||||
socket_connector_service::
|
||||
connect(
|
||||
impl_type& impl,
|
||||
peer_type& peer_socket,
|
||||
const socket_address& peer_address)
|
||||
{
|
||||
// We cannot connect a socket that is already open.
|
||||
if (peer_socket.impl() != invalid_socket)
|
||||
boost::throw_exception(socket_error(socket_error::already_connected));
|
||||
|
||||
// Create a new socket for the connection. This will not be put into the
|
||||
// stream_socket object until the connection has beenestablished.
|
||||
socket_holder sock(socket_ops::socket(peer_address.family(), SOCK_STREAM,
|
||||
IPPROTO_TCP));
|
||||
if (sock.get() == invalid_socket)
|
||||
boost::throw_exception(socket_error(socket_ops::get_error()));
|
||||
|
||||
// Perform the connect operation itself.
|
||||
impl->add_socket(sock.get());
|
||||
int result = socket_ops::connect(sock.get(), peer_address.native_address(),
|
||||
peer_address.native_size());
|
||||
impl->remove_socket(sock.get());
|
||||
if (result == socket_error_retval)
|
||||
boost::throw_exception(socket_error(socket_ops::get_error()));
|
||||
|
||||
// Connection was successful. The stream_socket object will now take
|
||||
// ownership of the newly connected native socket handle.
|
||||
peer_socket.set_impl(sock.release());
|
||||
}
|
||||
|
||||
void
|
||||
socket_connector_service::
|
||||
async_connect(
|
||||
impl_type& impl,
|
||||
peer_type& peer_socket,
|
||||
const socket_address& peer_address,
|
||||
const connect_handler& handler,
|
||||
completion_context& context)
|
||||
{
|
||||
do_socket_connector_async_connect(impl, peer_socket, peer_address, handler,
|
||||
context);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
@ -17,8 +17,18 @@
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <boost/function.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/basic_stream_socket.hpp"
|
||||
#include "asio/service.hpp"
|
||||
#include "asio/service_type_id.hpp"
|
||||
#include "asio/detail/stream_socket_service.hpp"
|
||||
|
||||
namespace asio { class completion_context; }
|
||||
namespace asio { class socket_address; }
|
||||
namespace asio { class socket_error; }
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
@ -29,17 +39,18 @@ 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.
|
||||
// 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);
|
||||
// The type of the stream sockets that will be connected.
|
||||
typedef basic_stream_socket<stream_socket_service> peer_type;
|
||||
|
||||
// The value to use for uninitialised implementations.
|
||||
static const impl_type invalid_impl = 0;
|
||||
|
||||
// Create a new socket connector implementation.
|
||||
void create(impl_type& impl);
|
||||
@ -48,36 +59,28 @@ public:
|
||||
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);
|
||||
// socket_error exception on error.
|
||||
void connect(impl_type& impl, peer_type& peer_socket,
|
||||
const socket_address& peer_address);
|
||||
|
||||
// The type of a handler called when the asynchronous connect completes. The
|
||||
// only argument is the error code.
|
||||
typedef boost::function1<void, const socket_error&> connect_handler;
|
||||
|
||||
// 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,
|
||||
void async_connect(impl_type& impl, peer_type& 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);
|
||||
completion_context& context);
|
||||
|
||||
private:
|
||||
// Destroy a socket connector implementation.
|
||||
virtual void do_socket_connector_destroy(impl_type& impl) = 0;
|
||||
|
||||
// Start an asynchronous connect.
|
||||
virtual void do_socket_connector_async_connect(impl_type& impl,
|
||||
peer_type& peer_socket, const socket_address& peer_address,
|
||||
const connect_handler& handler, completion_context& context) = 0;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -14,10 +14,176 @@
|
||||
|
||||
#include "asio/detail/stream_socket_service.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/socket_error.hpp"
|
||||
#include "asio/detail/socket_ops.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
const service_type_id stream_socket_service::id;
|
||||
|
||||
const stream_socket_service::impl_type stream_socket_service::invalid_impl;
|
||||
|
||||
void
|
||||
stream_socket_service::
|
||||
create(
|
||||
impl_type& impl,
|
||||
impl_type new_impl)
|
||||
{
|
||||
do_stream_socket_create(impl, new_impl);
|
||||
}
|
||||
|
||||
void
|
||||
stream_socket_service::
|
||||
destroy(
|
||||
impl_type& impl)
|
||||
{
|
||||
do_stream_socket_destroy(impl);
|
||||
}
|
||||
|
||||
size_t
|
||||
stream_socket_service::
|
||||
send(
|
||||
impl_type& impl,
|
||||
const void* data,
|
||||
size_t length)
|
||||
{
|
||||
int bytes_sent = socket_ops::send(impl, data, length, 0);
|
||||
if (bytes_sent < 0)
|
||||
boost::throw_exception(socket_error(socket_ops::get_error()));
|
||||
return bytes_sent;
|
||||
}
|
||||
|
||||
void
|
||||
stream_socket_service::
|
||||
async_send(
|
||||
impl_type& impl,
|
||||
const void* data,
|
||||
size_t length,
|
||||
const send_handler& handler,
|
||||
completion_context& context)
|
||||
{
|
||||
do_stream_socket_async_send(impl, data, length, handler, context);
|
||||
}
|
||||
|
||||
size_t
|
||||
stream_socket_service::
|
||||
send_n(
|
||||
impl_type& impl,
|
||||
const void* data,
|
||||
size_t length,
|
||||
size_t* total_bytes_sent)
|
||||
{
|
||||
// TODO handle non-blocking sockets using select to wait until ready.
|
||||
|
||||
int bytes_sent = 0;
|
||||
size_t total_sent = 0;
|
||||
while (total_sent < length)
|
||||
{
|
||||
bytes_sent = socket_ops::send(impl,
|
||||
static_cast<const char*>(data) + total_sent, length - total_sent, 0);
|
||||
if (bytes_sent < 0)
|
||||
{
|
||||
boost::throw_exception(socket_error(socket_ops::get_error()));
|
||||
}
|
||||
else if (bytes_sent == 0)
|
||||
{
|
||||
if (total_bytes_sent)
|
||||
*total_bytes_sent = total_sent;
|
||||
return bytes_sent;
|
||||
}
|
||||
total_sent += bytes_sent;
|
||||
}
|
||||
if (total_bytes_sent)
|
||||
*total_bytes_sent = total_sent;
|
||||
return bytes_sent;
|
||||
}
|
||||
|
||||
void
|
||||
stream_socket_service::
|
||||
async_send_n(
|
||||
impl_type& impl,
|
||||
const void* data,
|
||||
size_t length,
|
||||
const send_n_handler& handler,
|
||||
completion_context& context)
|
||||
{
|
||||
do_stream_socket_async_send_n(impl, data, length, handler, context);
|
||||
}
|
||||
|
||||
size_t
|
||||
stream_socket_service::
|
||||
recv(
|
||||
impl_type& impl,
|
||||
void* data,
|
||||
size_t max_length)
|
||||
{
|
||||
int bytes_recvd = socket_ops::recv(impl, data, max_length, 0);
|
||||
if (bytes_recvd < 0)
|
||||
boost::throw_exception(socket_error(socket_ops::get_error()));
|
||||
return bytes_recvd;
|
||||
}
|
||||
|
||||
void
|
||||
stream_socket_service::
|
||||
async_recv(
|
||||
impl_type& impl,
|
||||
void* data,
|
||||
size_t max_length,
|
||||
const recv_handler& handler,
|
||||
completion_context& context)
|
||||
{
|
||||
do_stream_socket_async_recv(impl, data, max_length, handler, context);
|
||||
}
|
||||
|
||||
size_t
|
||||
stream_socket_service::
|
||||
recv_n(
|
||||
impl_type& impl,
|
||||
void* data,
|
||||
size_t length,
|
||||
size_t* total_bytes_recvd)
|
||||
{
|
||||
// TODO handle non-blocking sockets using select to wait until ready.
|
||||
|
||||
int bytes_recvd = 0;
|
||||
size_t total_recvd = 0;
|
||||
while (total_recvd < length)
|
||||
{
|
||||
bytes_recvd = socket_ops::recv(impl,
|
||||
static_cast<char*>(data) + total_recvd, length - total_recvd, 0);
|
||||
if (bytes_recvd < 0)
|
||||
{
|
||||
boost::throw_exception(socket_error(socket_ops::get_error()));
|
||||
}
|
||||
else if (bytes_recvd == 0)
|
||||
{
|
||||
if (total_bytes_recvd)
|
||||
*total_bytes_recvd = total_recvd;
|
||||
return bytes_recvd;
|
||||
}
|
||||
total_recvd += bytes_recvd;
|
||||
}
|
||||
if (total_bytes_recvd)
|
||||
*total_bytes_recvd = total_recvd;
|
||||
return bytes_recvd;
|
||||
}
|
||||
|
||||
void
|
||||
stream_socket_service::
|
||||
async_recv_n(
|
||||
impl_type& impl,
|
||||
void* data,
|
||||
size_t length,
|
||||
const recv_n_handler& handler,
|
||||
completion_context& context)
|
||||
{
|
||||
do_stream_socket_async_recv_n(impl, data, length, handler, context);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
@ -17,9 +17,16 @@
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <boost/function.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/service.hpp"
|
||||
#include "asio/service_type_id.hpp"
|
||||
#include "asio/stream_socket.hpp"
|
||||
#include "asio/detail/socket_types.hpp"
|
||||
|
||||
namespace asio { class completion_context; }
|
||||
namespace asio { class socket_error; }
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
@ -28,47 +35,114 @@ class stream_socket_service
|
||||
: public virtual service
|
||||
{
|
||||
public:
|
||||
typedef stream_socket::send_handler send_handler;
|
||||
typedef stream_socket::send_n_handler send_n_handler;
|
||||
typedef stream_socket::recv_handler recv_handler;
|
||||
typedef stream_socket::recv_n_handler recv_n_handler;
|
||||
|
||||
// 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.
|
||||
virtual void register_stream_socket(stream_socket& socket) = 0;
|
||||
// The native type of the stream socket. This type is dependent on the
|
||||
// underlying implementation of the socket layer.
|
||||
typedef socket_type impl_type;
|
||||
|
||||
// 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;
|
||||
// The value to use for uninitialised implementations.
|
||||
static const impl_type invalid_impl = invalid_socket;
|
||||
|
||||
// Create a new socket connector implementation.
|
||||
void create(impl_type& impl, impl_type new_impl);
|
||||
|
||||
// Destroy a socket connector implementation.
|
||||
void destroy(impl_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.
|
||||
size_t send(impl_type& impl, const void* data, size_t length);
|
||||
|
||||
// The handler when a send operation is completed. The first argument is the
|
||||
// error code, the second is the number of bytes sent.
|
||||
typedef boost::function2<void, const socket_error&, size_t> send_handler;
|
||||
|
||||
// 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;
|
||||
void async_send(impl_type& impl, const void* data, size_t length,
|
||||
const send_handler& handler, completion_context& context);
|
||||
|
||||
// Send all of the given data to the peer before returning. Returns the
|
||||
// number of bytes sent on the last send or 0 if the connection was closed
|
||||
// cleanly. Throws a socket_error exception on failure.
|
||||
size_t send_n(impl_type& impl, const void* data, size_t length,
|
||||
size_t* total_bytes_sent);
|
||||
|
||||
// The handler when a send_n operation is completed. The first argument is
|
||||
// the error code, the second is the total number of bytes sent, and the
|
||||
// third is the number of bytes sent in the last send operation.
|
||||
typedef boost::function3<void, const socket_error&, size_t, size_t>
|
||||
send_n_handler;
|
||||
|
||||
// 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;
|
||||
void async_send_n(impl_type& impl, const void* data, size_t length,
|
||||
const send_n_handler& handler, completion_context& context);
|
||||
|
||||
// Receive some data from the peer. Returns the number of bytes received or
|
||||
// 0 if the connection was closed cleanly. Throws a socket_error exception
|
||||
// on failure.
|
||||
size_t recv(impl_type& impl, void* data, size_t max_length);
|
||||
|
||||
// The handler when a recv operation is completed. The first argument is the
|
||||
// error code, the second is the number of bytes received.
|
||||
typedef boost::function2<void, const socket_error&, size_t> recv_handler;
|
||||
|
||||
// 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;
|
||||
void async_recv(impl_type& impl, void* data, size_t max_length,
|
||||
const recv_handler& handler, completion_context& context);
|
||||
|
||||
// Receive the specified amount of data from the peer. Returns the number of
|
||||
// bytes received on the last recv call or 0 if the connection
|
||||
// was closed cleanly. Throws a socket_error exception on failure.
|
||||
size_t recv_n(impl_type& impl, void* data, size_t length,
|
||||
size_t* total_bytes_recvd);
|
||||
|
||||
// The handler when a recv_n operation is completed. The first argument is
|
||||
// the error code, the second is the number of bytes received, the third is
|
||||
// the number of bytes received in the last recv operation.
|
||||
typedef boost::function3<void, const socket_error&, size_t, size_t>
|
||||
recv_n_handler;
|
||||
|
||||
// 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,
|
||||
void async_recv_n(impl_type& impl, void* data, size_t length,
|
||||
const recv_n_handler& handler, completion_context& context);
|
||||
|
||||
private:
|
||||
// Create a new socket connector implementation.
|
||||
virtual void do_stream_socket_create(impl_type& impl,
|
||||
impl_type new_impl) = 0;
|
||||
|
||||
// Destroy a socket connector implementation.
|
||||
virtual void do_stream_socket_destroy(impl_type& impl) = 0;
|
||||
|
||||
// Start an asynchronous send.
|
||||
virtual void do_stream_socket_async_send(impl_type& impl, 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.
|
||||
virtual void do_stream_socket_async_send_n(impl_type& impl, const void* data,
|
||||
size_t length, const send_n_handler& handler,
|
||||
completion_context& context) = 0;
|
||||
|
||||
// Start an asynchronous receive.
|
||||
virtual void do_stream_socket_async_recv(impl_type& impl, 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.
|
||||
virtual void do_stream_socket_async_recv_n(impl_type& impl, void* data,
|
||||
size_t length, const recv_n_handler& handler,
|
||||
completion_context& context) = 0;
|
||||
};
|
||||
|
@ -22,10 +22,11 @@
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/completion_context.hpp"
|
||||
#include "asio/service.hpp"
|
||||
#include "asio/service_type_id.hpp"
|
||||
|
||||
namespace asio { class completion_context; }
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
@ -36,23 +37,22 @@ public:
|
||||
// The service type id.
|
||||
static const service_type_id id;
|
||||
|
||||
/// The handler for when a timer expires.
|
||||
// The handler for when a timer expires.
|
||||
typedef boost::function0<void> 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.
|
||||
// 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());
|
||||
const timer_handler& handler, completion_context& 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.
|
||||
// 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());
|
||||
completion_context& context);
|
||||
|
||||
/// Cancel the timer with the given id.
|
||||
// Cancel the timer with the given id.
|
||||
void cancel_timer(void* owner, int timer_id);
|
||||
|
||||
private:
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/dgram_socket.hpp"
|
||||
#include "asio/basic_dgram_socket.hpp"
|
||||
#include "asio/detail/dgram_socket_service.hpp"
|
||||
|
||||
namespace asio {
|
||||
|
@ -1,172 +0,0 @@
|
||||
//
|
||||
// socket_acceptor.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/socket_acceptor.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <cassert>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/demuxer.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"
|
||||
|
||||
namespace asio {
|
||||
|
||||
socket_acceptor::
|
||||
socket_acceptor(
|
||||
demuxer& d)
|
||||
: service_(dynamic_cast<detail::socket_acceptor_service&>(
|
||||
d.get_service(detail::socket_acceptor_service::id))),
|
||||
handle_(detail::invalid_socket)
|
||||
{
|
||||
}
|
||||
|
||||
socket_acceptor::
|
||||
socket_acceptor(
|
||||
demuxer& d,
|
||||
const socket_address& addr,
|
||||
int listen_queue)
|
||||
: service_(dynamic_cast<detail::socket_acceptor_service&>(
|
||||
d.get_service(detail::socket_acceptor_service::id))),
|
||||
handle_(detail::invalid_socket)
|
||||
{
|
||||
open(addr, listen_queue);
|
||||
}
|
||||
|
||||
socket_acceptor::
|
||||
~socket_acceptor()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
void
|
||||
socket_acceptor::
|
||||
open(
|
||||
const socket_address& addr,
|
||||
int listen_queue)
|
||||
{
|
||||
assert(handle_ == detail::invalid_socket);
|
||||
|
||||
detail::socket_holder sock(detail::socket_ops::socket(addr.family(),
|
||||
SOCK_STREAM, IPPROTO_TCP));
|
||||
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()));
|
||||
|
||||
if (detail::socket_ops::listen(sock.get(), listen_queue)
|
||||
== detail::socket_error_retval)
|
||||
boost::throw_exception(socket_error(detail::socket_ops::get_error()));
|
||||
|
||||
handle_ = sock.release();
|
||||
|
||||
service_.register_socket_acceptor(*this);
|
||||
}
|
||||
|
||||
void
|
||||
socket_acceptor::
|
||||
close()
|
||||
{
|
||||
if (handle_ != detail::invalid_socket)
|
||||
{
|
||||
service_.deregister_socket_acceptor(*this);
|
||||
detail::socket_ops::close(handle_);
|
||||
handle_ = detail::invalid_socket;
|
||||
}
|
||||
}
|
||||
|
||||
socket_acceptor::native_type
|
||||
socket_acceptor::
|
||||
native_handle() const
|
||||
{
|
||||
return handle_;
|
||||
}
|
||||
|
||||
void
|
||||
socket_acceptor::
|
||||
accept_i(
|
||||
stream_socket& peer_socket)
|
||||
{
|
||||
// We cannot accept a socket that is already open.
|
||||
if (peer_socket.native_handle() != detail::invalid_socket)
|
||||
boost::throw_exception(socket_error(socket_error::already_connected));
|
||||
|
||||
detail::socket_type new_socket = detail::socket_ops::accept(handle_, 0, 0);
|
||||
if (int error = detail::socket_ops::get_error())
|
||||
boost::throw_exception(socket_error(error));
|
||||
peer_socket.associate(new_socket);
|
||||
}
|
||||
|
||||
void
|
||||
socket_acceptor::
|
||||
accept_i(
|
||||
stream_socket& peer_socket,
|
||||
socket_address& peer_address)
|
||||
{
|
||||
// We cannot accept a socket that is already open.
|
||||
if (peer_socket.native_handle() != detail::invalid_socket)
|
||||
boost::throw_exception(socket_error(socket_error::already_connected));
|
||||
|
||||
detail::socket_addr_len_type addr_len = peer_address.native_size();
|
||||
detail::socket_type new_socket = detail::socket_ops::accept(handle_,
|
||||
peer_address.native_address(), &addr_len);
|
||||
if (int error = detail::socket_ops::get_error())
|
||||
boost::throw_exception(socket_error(error));
|
||||
peer_address.native_size(addr_len);
|
||||
peer_socket.associate(new_socket);
|
||||
}
|
||||
|
||||
void
|
||||
socket_acceptor::
|
||||
async_accept_i(
|
||||
stream_socket& peer_socket,
|
||||
const accept_handler& handler,
|
||||
completion_context& context)
|
||||
{
|
||||
service_.async_socket_accept(*this, peer_socket, handler, context);
|
||||
}
|
||||
|
||||
void
|
||||
socket_acceptor::
|
||||
async_accept_i(
|
||||
stream_socket& peer_socket,
|
||||
socket_address& peer_address,
|
||||
const accept_handler& handler,
|
||||
completion_context& context)
|
||||
{
|
||||
service_.async_socket_accept(*this, peer_socket, peer_address, handler,
|
||||
context);
|
||||
}
|
||||
|
||||
void
|
||||
socket_acceptor::
|
||||
associate(
|
||||
stream_socket& peer_socket,
|
||||
stream_socket::native_type handle)
|
||||
{
|
||||
peer_socket.associate(handle);
|
||||
}
|
||||
|
||||
} // namespace asio
|
@ -17,138 +17,14 @@
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/completion_context.hpp"
|
||||
#include "asio/stream_socket.hpp"
|
||||
#include "asio/detail/socket_types.hpp"
|
||||
#include "asio/basic_socket_acceptor.hpp"
|
||||
#include "asio/detail/socket_acceptor_service.hpp"
|
||||
|
||||
namespace asio {
|
||||
|
||||
class demuxer;
|
||||
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
|
||||
: 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;
|
||||
|
||||
/// Constructor an acceptor without opening it. The acceptor needs to be
|
||||
/// opened before it can accept new connections.
|
||||
explicit socket_acceptor(demuxer& d);
|
||||
|
||||
/// Construct an acceptor opened on the given address and with the listen
|
||||
/// queue set to the given number of connections.
|
||||
socket_acceptor(demuxer& d, const socket_address& addr,
|
||||
int listen_queue = SOMAXCONN);
|
||||
|
||||
/// Destructor.
|
||||
~socket_acceptor();
|
||||
|
||||
/// Open the acceptor using the given address and length of the listen queue.
|
||||
void open(const socket_address& addr, int listen_queue = SOMAXCONN);
|
||||
|
||||
/// Close the acceptor.
|
||||
void close();
|
||||
|
||||
/// Get the underlying handle in the native type.
|
||||
native_type native_handle() const;
|
||||
|
||||
/// Accept a new connection. Throws a socket_error exception on failure.
|
||||
template <typename Stream>
|
||||
void accept(Stream& peer_socket)
|
||||
{
|
||||
accept_i(peer_socket.lowest_layer());
|
||||
}
|
||||
|
||||
/// Accept a new connection. Throws a socket_error exception on failure.
|
||||
template <typename Stream>
|
||||
void accept(Stream& peer_socket, socket_address& peer_address)
|
||||
{
|
||||
accept_i(peer_socket.lowest_layer(), peer_address);
|
||||
}
|
||||
|
||||
/// The type of a handler called when the asynchronous accept completes. The
|
||||
/// only argument is the error code.
|
||||
typedef boost::function1<void, const socket_error&> accept_handler;
|
||||
|
||||
/// Start an asynchronous accept. The peer_socket object must be valid until
|
||||
/// the accept's completion handler is invoked.
|
||||
template <typename Stream>
|
||||
void async_accept(Stream& peer_socket, const accept_handler& handler)
|
||||
{
|
||||
async_accept_i(peer_socket.lowest_layer(), handler);
|
||||
}
|
||||
|
||||
/// Start an asynchronous accept. The peer_socket object must be valid until
|
||||
/// the accept's completion handler is invoked.
|
||||
template <typename Stream>
|
||||
void async_accept(Stream& peer_socket, const accept_handler& handler,
|
||||
completion_context& context)
|
||||
{
|
||||
async_accept_i(peer_socket.lowest_layer(), handler, context);
|
||||
}
|
||||
|
||||
/// Start an asynchronous accept. The peer_socket and peer_address objects
|
||||
/// must be valid until the accept's completion handler is invoked.
|
||||
template <typename Stream>
|
||||
void async_accept(Stream& peer_socket, socket_address& peer_address,
|
||||
const accept_handler& handler)
|
||||
{
|
||||
async_accept_i(peer_socket.lowest_layer(), peer_address, handler);
|
||||
}
|
||||
|
||||
/// Start an asynchronous accept. The peer_socket and peer_address objects
|
||||
/// must be valid until the accept's completion handler is invoked.
|
||||
template <typename Stream>
|
||||
void async_accept(Stream& peer_socket, socket_address& peer_address,
|
||||
const accept_handler& handler, completion_context& context)
|
||||
{
|
||||
async_accept_i(peer_socket.lowest_layer(), peer_address, handler, context);
|
||||
}
|
||||
|
||||
private:
|
||||
/// The socket_acceptor_service class is permitted to call the associate()
|
||||
/// function.
|
||||
friend class detail::socket_acceptor_service;
|
||||
|
||||
// Accept a new connection. Throws a socket_error exception on failure.
|
||||
void accept_i(stream_socket& peer_socket);
|
||||
|
||||
// Accept a new connection. Throws a socket_error exception on failure.
|
||||
void accept_i(stream_socket& peer_socket, socket_address& peer_address);
|
||||
|
||||
// Start an asynchronous accept. The peer_socket object must be valid until
|
||||
// the accept's completion handler is invoked.
|
||||
void async_accept_i(stream_socket& peer_socket,
|
||||
const accept_handler& handler,
|
||||
completion_context& context = completion_context::null());
|
||||
|
||||
// Start an asynchronous accept. The peer_socket and peer_address objects
|
||||
// must be valid until the accept's completion handler is invoked.
|
||||
void async_accept_i(stream_socket& peer_socket, socket_address& peer_address,
|
||||
const accept_handler& handler,
|
||||
completion_context& context = completion_context::null());
|
||||
|
||||
/// Associate the given stream socket with the native socket handle.
|
||||
void associate(stream_socket& peer_socket,
|
||||
stream_socket::native_type handle);
|
||||
|
||||
/// The backend service implementation.
|
||||
detail::socket_acceptor_service& service_;
|
||||
|
||||
/// The underlying native handle.
|
||||
native_type handle_;
|
||||
};
|
||||
/// Typedef for the typical usage of socket_acceptor.
|
||||
typedef basic_socket_acceptor<detail::socket_acceptor_service>
|
||||
socket_acceptor;
|
||||
|
||||
} // namespace asio
|
||||
|
||||
|
@ -1,127 +0,0 @@
|
||||
//
|
||||
// socket_connector.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/socket_connector.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <cassert>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/demuxer.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"
|
||||
|
||||
namespace asio {
|
||||
|
||||
socket_connector::
|
||||
socket_connector(
|
||||
demuxer& d)
|
||||
: service_(dynamic_cast<detail::socket_connector_service&>(
|
||||
d.get_service(detail::socket_connector_service::id))),
|
||||
impl_(new detail::socket_connector_impl)
|
||||
{
|
||||
service_.register_socket_connector(*this);
|
||||
}
|
||||
|
||||
socket_connector::
|
||||
~socket_connector()
|
||||
{
|
||||
delete impl_;
|
||||
}
|
||||
|
||||
void
|
||||
socket_connector::
|
||||
open()
|
||||
{
|
||||
assert(impl_ == 0);
|
||||
impl_ = new detail::socket_connector_impl;
|
||||
service_.register_socket_connector(*this);
|
||||
}
|
||||
|
||||
void
|
||||
socket_connector::
|
||||
close()
|
||||
{
|
||||
if (impl_)
|
||||
{
|
||||
service_.deregister_socket_connector(*this);
|
||||
delete impl_;
|
||||
impl_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
socket_connector::native_type
|
||||
socket_connector::
|
||||
native_handle() const
|
||||
{
|
||||
return impl_;
|
||||
}
|
||||
|
||||
void
|
||||
socket_connector::
|
||||
connect_i(
|
||||
stream_socket& peer_socket,
|
||||
const socket_address& peer_address)
|
||||
{
|
||||
// We cannot connect a socket that is already open.
|
||||
if (peer_socket.native_handle() != detail::invalid_socket)
|
||||
boost::throw_exception(socket_error(socket_error::already_connected));
|
||||
|
||||
// Create a new socket for the connection. This will not be put into the
|
||||
// stream_socket object until the connection has beenestablished.
|
||||
detail::socket_holder sock(detail::socket_ops::socket(peer_address.family(),
|
||||
SOCK_STREAM, IPPROTO_TCP));
|
||||
if (sock.get() == detail::invalid_socket)
|
||||
boost::throw_exception(socket_error(detail::socket_ops::get_error()));
|
||||
|
||||
// Perform the connect operation itself.
|
||||
impl_->add_socket(sock.get());
|
||||
int result = detail::socket_ops::connect(sock.get(),
|
||||
peer_address.native_address(), peer_address.native_size());
|
||||
impl_->remove_socket(sock.get());
|
||||
if (result == detail::socket_error_retval)
|
||||
boost::throw_exception(socket_error(detail::socket_ops::get_error()));
|
||||
|
||||
// Connection was successful. The stream_socket object will now take
|
||||
// ownership of the newly connected native socket handle.
|
||||
peer_socket.associate(sock.release());
|
||||
}
|
||||
|
||||
void
|
||||
socket_connector::
|
||||
async_connect_i(
|
||||
stream_socket& peer_socket,
|
||||
const socket_address& peer_address,
|
||||
const connect_handler& handler,
|
||||
completion_context& context)
|
||||
{
|
||||
service_.async_socket_connect(*this, peer_socket, peer_address, handler,
|
||||
context);
|
||||
}
|
||||
|
||||
void
|
||||
socket_connector::
|
||||
associate(
|
||||
stream_socket& peer_socket,
|
||||
stream_socket::native_type handle)
|
||||
{
|
||||
peer_socket.associate(handle);
|
||||
}
|
||||
|
||||
} // namespace asio
|
@ -17,106 +17,14 @@
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/completion_context.hpp"
|
||||
#include "asio/stream_socket.hpp"
|
||||
#include "asio/detail/socket_types.hpp"
|
||||
#include "asio/basic_socket_connector.hpp"
|
||||
#include "asio/detail/socket_connector_service.hpp"
|
||||
|
||||
namespace asio {
|
||||
|
||||
class demuxer;
|
||||
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
|
||||
/// endpoint.
|
||||
class socket_connector
|
||||
: private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
/// The native type of the socket connector. This type is dependent on the
|
||||
/// underlying implementation of the socket layer.
|
||||
typedef detail::socket_connector_impl* native_type;
|
||||
|
||||
/// Constructor a connector. The connector is automatically opened.
|
||||
explicit socket_connector(demuxer& d);
|
||||
|
||||
/// Destructor.
|
||||
~socket_connector();
|
||||
|
||||
/// Open the connector.
|
||||
void open();
|
||||
|
||||
/// Close the connector.
|
||||
void close();
|
||||
|
||||
/// Get the underlying handle in the native type.
|
||||
native_type native_handle() const;
|
||||
|
||||
/// Connect the given socket to the peer at the specified address. Throws a
|
||||
/// socket_error exception on failure.
|
||||
template <typename Stream>
|
||||
void connect(Stream& peer_socket, const socket_address& peer_address)
|
||||
{
|
||||
connect_i(peer_socket.lowest_layer(), peer_address);
|
||||
}
|
||||
|
||||
/// The type of a handler called when the asynchronous connect completes. The
|
||||
/// only argument is the error code.
|
||||
typedef boost::function1<void, const socket_error&> connect_handler;
|
||||
|
||||
/// Start an asynchronous connect. The peer_socket object must be valid until
|
||||
/// the connect's completion handler is invoked.
|
||||
template <typename Stream>
|
||||
void async_connect(Stream& peer_socket,
|
||||
const socket_address& peer_address, const connect_handler& handler)
|
||||
{
|
||||
async_connect_i(peer_socket.lowest_layer(), peer_address, handler);
|
||||
}
|
||||
|
||||
/// Start an asynchronous connect. The peer_socket object must be valid until
|
||||
/// the connect's completion handler is invoked.
|
||||
template <typename Stream>
|
||||
void async_connect(Stream& peer_socket,
|
||||
const socket_address& peer_address, const connect_handler& handler,
|
||||
completion_context& context)
|
||||
{
|
||||
async_connect_i(peer_socket.lowest_layer(), peer_address, handler,
|
||||
context);
|
||||
}
|
||||
|
||||
private:
|
||||
/// The socket_connector_service is permitted to call the associate()
|
||||
/// function.
|
||||
friend class detail::socket_connector_service;
|
||||
|
||||
// Connect the given socket to the peer at the specified address. Throws a
|
||||
// socket_error exception on failure.
|
||||
void connect_i(stream_socket& 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_i(stream_socket& peer_socket,
|
||||
const socket_address& peer_address, const connect_handler& handler,
|
||||
completion_context& context = completion_context::null());
|
||||
|
||||
/// Associate the given stream socket with the native socket handle.
|
||||
void associate(stream_socket& peer_socket,
|
||||
stream_socket::native_type handle);
|
||||
|
||||
/// The backend service implementation.
|
||||
detail::socket_connector_service& service_;
|
||||
|
||||
/// The underlying implementation.
|
||||
detail::socket_connector_impl* impl_;
|
||||
};
|
||||
/// Typedef for the typical usage of socket_connector.
|
||||
typedef basic_socket_connector<detail::socket_connector_service>
|
||||
socket_connector;
|
||||
|
||||
} // namespace asio
|
||||
|
||||
|
@ -1,213 +0,0 @@
|
||||
//
|
||||
// stream_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/stream_socket.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <cassert>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/demuxer.hpp"
|
||||
#include "asio/socket_error.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<detail::stream_socket_service&>(
|
||||
d.get_service(detail::stream_socket_service::id))),
|
||||
handle_(detail::invalid_socket)
|
||||
{
|
||||
}
|
||||
|
||||
stream_socket::
|
||||
~stream_socket()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
void
|
||||
stream_socket::
|
||||
close()
|
||||
{
|
||||
if (handle_ != detail::invalid_socket)
|
||||
{
|
||||
service_.deregister_stream_socket(*this);
|
||||
detail::socket_ops::close(handle_);
|
||||
handle_ = detail::invalid_socket;
|
||||
}
|
||||
}
|
||||
|
||||
stream_socket::lowest_layer_type&
|
||||
stream_socket::
|
||||
lowest_layer()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
stream_socket::native_type
|
||||
stream_socket::
|
||||
native_handle() const
|
||||
{
|
||||
return handle_;
|
||||
}
|
||||
|
||||
size_t
|
||||
stream_socket::
|
||||
send(
|
||||
const void* data,
|
||||
size_t length)
|
||||
{
|
||||
int bytes_sent = detail::socket_ops::send(handle_, data, length, 0);
|
||||
if (bytes_sent < 0)
|
||||
boost::throw_exception(socket_error(detail::socket_ops::get_error()));
|
||||
return bytes_sent;
|
||||
}
|
||||
|
||||
void
|
||||
stream_socket::
|
||||
async_send(
|
||||
const void* data,
|
||||
size_t length,
|
||||
const send_handler& handler,
|
||||
completion_context& context)
|
||||
{
|
||||
service_.async_stream_socket_send(*this, data, length, handler, context);
|
||||
}
|
||||
|
||||
size_t
|
||||
stream_socket::
|
||||
send_n(
|
||||
const void* data,
|
||||
size_t length,
|
||||
size_t* total_bytes_sent)
|
||||
{
|
||||
// TODO handle non-blocking sockets using select to wait until ready.
|
||||
|
||||
int bytes_sent = 0;
|
||||
size_t total_sent = 0;
|
||||
while (total_sent < length)
|
||||
{
|
||||
bytes_sent = detail::socket_ops::send(handle_,
|
||||
static_cast<const char*>(data) + total_sent, length - total_sent, 0);
|
||||
if (bytes_sent < 0)
|
||||
{
|
||||
boost::throw_exception(socket_error(detail::socket_ops::get_error()));
|
||||
}
|
||||
else if (bytes_sent == 0)
|
||||
{
|
||||
if (total_bytes_sent)
|
||||
*total_bytes_sent = total_sent;
|
||||
return bytes_sent;
|
||||
}
|
||||
total_sent += bytes_sent;
|
||||
}
|
||||
if (total_bytes_sent)
|
||||
*total_bytes_sent = total_sent;
|
||||
return bytes_sent;
|
||||
}
|
||||
|
||||
void
|
||||
stream_socket::
|
||||
async_send_n(
|
||||
const void* data,
|
||||
size_t length,
|
||||
const send_n_handler& handler,
|
||||
completion_context& context)
|
||||
{
|
||||
service_.async_stream_socket_send_n(*this, data, length, handler, context);
|
||||
}
|
||||
|
||||
size_t
|
||||
stream_socket::
|
||||
recv(
|
||||
void* data,
|
||||
size_t max_length)
|
||||
{
|
||||
int bytes_recvd = detail::socket_ops::recv(handle_, data, max_length, 0);
|
||||
if (bytes_recvd < 0)
|
||||
boost::throw_exception(socket_error(detail::socket_ops::get_error()));
|
||||
return bytes_recvd;
|
||||
}
|
||||
|
||||
void
|
||||
stream_socket::
|
||||
async_recv(
|
||||
void* data,
|
||||
size_t max_length,
|
||||
const recv_handler& handler,
|
||||
completion_context& context)
|
||||
{
|
||||
service_.async_stream_socket_recv(*this, data, max_length, handler, context);
|
||||
}
|
||||
|
||||
size_t
|
||||
stream_socket::
|
||||
recv_n(
|
||||
void* data,
|
||||
size_t length,
|
||||
size_t* total_bytes_recvd)
|
||||
{
|
||||
// TODO handle non-blocking sockets using select to wait until ready.
|
||||
|
||||
int bytes_recvd = 0;
|
||||
size_t total_recvd = 0;
|
||||
while (total_recvd < length)
|
||||
{
|
||||
bytes_recvd = detail::socket_ops::recv(handle_,
|
||||
static_cast<char*>(data) + total_recvd, length - total_recvd, 0);
|
||||
if (bytes_recvd < 0)
|
||||
{
|
||||
boost::throw_exception(socket_error(detail::socket_ops::get_error()));
|
||||
}
|
||||
else if (bytes_recvd == 0)
|
||||
{
|
||||
if (total_bytes_recvd)
|
||||
*total_bytes_recvd = total_recvd;
|
||||
return bytes_recvd;
|
||||
}
|
||||
total_recvd += bytes_recvd;
|
||||
}
|
||||
if (total_bytes_recvd)
|
||||
*total_bytes_recvd = total_recvd;
|
||||
return bytes_recvd;
|
||||
}
|
||||
|
||||
void
|
||||
stream_socket::
|
||||
async_recv_n(
|
||||
void* data,
|
||||
size_t length,
|
||||
const recv_n_handler& handler,
|
||||
completion_context& context)
|
||||
{
|
||||
service_.async_stream_socket_recv_n(*this, data, length, handler, context);
|
||||
}
|
||||
|
||||
void
|
||||
stream_socket::
|
||||
associate(
|
||||
native_type handle)
|
||||
{
|
||||
assert(handle_ == detail::invalid_socket);
|
||||
handle_ = handle;
|
||||
if (handle_ != detail::invalid_socket)
|
||||
service_.register_stream_socket(*this);
|
||||
}
|
||||
|
||||
} // namespace asio
|
@ -17,136 +17,13 @@
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/completion_context.hpp"
|
||||
#include "asio/detail/socket_types.hpp"
|
||||
#include "asio/basic_stream_socket.hpp"
|
||||
#include "asio/detail/stream_socket_service.hpp"
|
||||
|
||||
namespace asio {
|
||||
|
||||
class demuxer;
|
||||
class socket_acceptor;
|
||||
class socket_connector;
|
||||
class socket_error;
|
||||
namespace detail { class stream_socket_service; }
|
||||
|
||||
/// The stream_socket class provides asynchronous and blocking stream-oriented
|
||||
/// socket functionality.
|
||||
class stream_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;
|
||||
|
||||
/// A stream_socket is always the lowest layer.
|
||||
typedef stream_socket lowest_layer_type;
|
||||
|
||||
/// Construct a stream_socket without opening it. The socket needs to be
|
||||
/// connected or accepted before data can be sent or received on it.
|
||||
explicit stream_socket(demuxer& d);
|
||||
|
||||
/// Destructor.
|
||||
~stream_socket();
|
||||
|
||||
/// Close the socket.
|
||||
void close();
|
||||
|
||||
/// Get a reference to the lowest layer.
|
||||
lowest_layer_type& lowest_layer();
|
||||
|
||||
/// 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.
|
||||
size_t send(const void* data, size_t length);
|
||||
|
||||
/// The handler when a send operation is completed. The first argument is the
|
||||
/// error code, the second is the number of bytes sent.
|
||||
typedef boost::function2<void, const socket_error&, size_t> send_handler;
|
||||
|
||||
/// Start an asynchronous send. The data being sent must be valid for the
|
||||
/// lifetime of the asynchronous operation.
|
||||
void async_send(const void* data, size_t length,
|
||||
const send_handler& handler,
|
||||
completion_context& context = completion_context::null());
|
||||
|
||||
/// Send all of the given data to the peer before returning. Returns the
|
||||
/// number of bytes sent on the last send or 0 if the connection was closed
|
||||
/// cleanly. Throws a socket_error exception on failure.
|
||||
size_t send_n(const void* data, size_t length, size_t* total_bytes_sent = 0);
|
||||
|
||||
/// The handler when a send_n operation is completed. The first argument is
|
||||
/// the error code, the second is the total number of bytes sent, and the
|
||||
/// third is the number of bytes sent in the last send operation.
|
||||
typedef boost::function3<void, const socket_error&, size_t, size_t>
|
||||
send_n_handler;
|
||||
|
||||
/// 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.
|
||||
void async_send_n(const void* data, size_t length,
|
||||
const send_n_handler& handler,
|
||||
completion_context& context = completion_context::null());
|
||||
|
||||
/// Receive some data from the peer. Returns the number of bytes received or
|
||||
/// 0 if the connection was closed cleanly. Throws a socket_error exception
|
||||
/// on failure.
|
||||
size_t recv(void* data, size_t max_length);
|
||||
|
||||
/// The handler when a recv operation is completed. The first argument is the
|
||||
/// error code, the second is the number of bytes received.
|
||||
typedef boost::function2<void, const socket_error&, size_t> recv_handler;
|
||||
|
||||
/// Start an asynchronous receive. The buffer for the data being received must
|
||||
/// be valid for the lifetime of the asynchronous operation.
|
||||
void async_recv(void* data, size_t max_length,
|
||||
const recv_handler& handler,
|
||||
completion_context& context = completion_context::null());
|
||||
|
||||
/// Receive the specified amount of data from the peer. Returns the number of
|
||||
/// bytes received on the last recv call or 0 if the connection
|
||||
/// was closed cleanly. Throws a socket_error exception on failure.
|
||||
size_t recv_n(void* data, size_t length, size_t* total_bytes_recvd = 0);
|
||||
|
||||
/// The handler when a recv_n operation is completed. The first argument is
|
||||
/// the error code, the second is the number of bytes received, the third is
|
||||
/// the number of bytes received in the last recv operation.
|
||||
typedef boost::function3<void, const socket_error&, size_t, size_t>
|
||||
recv_n_handler;
|
||||
|
||||
/// 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.
|
||||
void async_recv_n(void* data, size_t length, const recv_n_handler& handler,
|
||||
completion_context& context = completion_context::null());
|
||||
|
||||
private:
|
||||
/// The socket_acceptor class is permitted to call the associate() function.
|
||||
friend class socket_acceptor;
|
||||
|
||||
/// The socket_connector class is permitted to call the associate() function.
|
||||
friend class socket_connector;
|
||||
|
||||
/// Associate the stream socket with the given native socket handle.
|
||||
void associate(native_type handle);
|
||||
|
||||
/// The backend service implementation.
|
||||
detail::stream_socket_service& service_;
|
||||
|
||||
/// The underlying native handle.
|
||||
native_type handle_;
|
||||
};
|
||||
/// Typedef for the typical usage of stream_socket.
|
||||
typedef basic_stream_socket<asio::detail::stream_socket_service> stream_socket;
|
||||
|
||||
} // namespace asio
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user