Finished adding per-operation error handler support. It is now only invoked
in case of error, never on success.
This commit is contained in:
parent
cc58f99de7
commit
e667e7ce1e
@ -90,9 +90,9 @@ public:
|
||||
* @param address An address on the local machine to which the dgram socket
|
||||
* will be bound.
|
||||
*
|
||||
* @param error_handler The handler to be called when an error occurs or when
|
||||
* the function completes successfully. Copies will be made of the handler as
|
||||
* required. The equivalent function signature of the handler must be:
|
||||
* @param error_handler The handler to be called when an error occurs. Copies
|
||||
* will be made of the handler as required. The equivalent function signature
|
||||
* of the handler must be:
|
||||
* @code void error_handler(
|
||||
* const asio::socket_error& error // Result of operation
|
||||
* ); @endcode
|
||||
@ -150,9 +150,9 @@ public:
|
||||
* @param address An address on the local machine to which the dgram socket
|
||||
* will be bound.
|
||||
*
|
||||
* @param error_handler The handler to be called when an error occurs or when
|
||||
* the function completes successfully. Copies will be made of the handler as
|
||||
* required. The equivalent function signature of the handler must be:
|
||||
* @param error_handler The handler to be called when an error occurs. Copies
|
||||
* will be made of the handler as required. The equivalent function signature
|
||||
* of the handler must be:
|
||||
* @code void error_handler(
|
||||
* const asio::socket_error& error // Result of operation
|
||||
* ); @endcode
|
||||
@ -207,9 +207,9 @@ public:
|
||||
*
|
||||
* @param option The new option value to be set on the socket.
|
||||
*
|
||||
* @param error_handler The handler to be called when an error occurs or when
|
||||
* the function completes successfully. Copies will be made of the handler as
|
||||
* required. The equivalent function signature of the handler must be:
|
||||
* @param error_handler The handler to be called when an error occurs. Copies
|
||||
* will be made of the handler as required. The equivalent function signature
|
||||
* of the handler must be:
|
||||
* @code void error_handler(
|
||||
* const asio::socket_error& error // Result of operation
|
||||
* ); @endcode
|
||||
@ -240,9 +240,9 @@ public:
|
||||
*
|
||||
* @param option The option value to be obtained from the socket.
|
||||
*
|
||||
* @param error_handler The handler to be called when an error occurs or when
|
||||
* the function completes successfully. Copies will be made of the handler as
|
||||
* required. The equivalent function signature of the handler must be:
|
||||
* @param error_handler The handler to be called when an error occurs. Copies
|
||||
* will be made of the handler as required. The equivalent function signature
|
||||
* of the handler must be:
|
||||
* @code void error_handler(
|
||||
* const asio::socket_error& error // Result of operation
|
||||
* ); @endcode
|
||||
@ -288,9 +288,9 @@ public:
|
||||
*
|
||||
* @param destination The remote address to which the data will be sent.
|
||||
*
|
||||
* @param error_handler The handler to be called when an error occurs or when
|
||||
* the function completes successfully. Copies will be made of the handler as
|
||||
* required. The equivalent function signature of the handler must be:
|
||||
* @param error_handler The handler to be called when an error occurs. Copies
|
||||
* will be made of the handler as required. The equivalent function signature
|
||||
* of the handler must be:
|
||||
* @code void error_handler(
|
||||
* const asio::socket_error& error // Result of operation
|
||||
* ); @endcode
|
||||
@ -413,9 +413,9 @@ public:
|
||||
* @param sender_address An address object that receives the address of the
|
||||
* remote sender of the datagram.
|
||||
*
|
||||
* @param error_handler The handler to be called when an error occurs or when
|
||||
* the function completes successfully. Copies will be made of the handler as
|
||||
* required. The equivalent function signature of the handler must be:
|
||||
* @param error_handler The handler to be called when an error occurs. Copies
|
||||
* will be made of the handler as required. The equivalent function signature
|
||||
* of the handler must be:
|
||||
* @code void error_handler(
|
||||
* const asio::socket_error& error // Result of operation
|
||||
* ); @endcode
|
||||
|
@ -97,9 +97,9 @@ public:
|
||||
* @param listen_queue The maximum length of the queue of pending
|
||||
* connections. A value of 0 means use the default queue length.
|
||||
*
|
||||
* @param error_handler The handler to be called when an error occurs or when
|
||||
* the function completes successfully. Copies will be made of the handler as
|
||||
* required. The equivalent function signature of the handler must be:
|
||||
* @param error_handler The handler to be called when an error occurs. Copies
|
||||
* will be made of the handler as required. The equivalent function signature
|
||||
* of the handler must be:
|
||||
* @code void error_handler(
|
||||
* const asio::socket_error& error // Result of operation
|
||||
* ); @endcode
|
||||
@ -163,9 +163,9 @@ public:
|
||||
* @param listen_queue The maximum length of the queue of pending
|
||||
* connections. A value of 0 means use the default queue length.
|
||||
*
|
||||
* @param error_handler The handler to be called when an error occurs or when
|
||||
* the function completes successfully. Copies will be made of the handler as
|
||||
* required. The equivalent function signature of the handler must be:
|
||||
* @param error_handler The handler to be called when an error occurs. Copies
|
||||
* will be made of the handler as required. The equivalent function signature
|
||||
* of the handler must be:
|
||||
* @code void error_handler(
|
||||
* const asio::socket_error& error // Result of operation
|
||||
* ); @endcode
|
||||
@ -220,9 +220,9 @@ public:
|
||||
*
|
||||
* @param option The new option value to be set on the acceptor.
|
||||
*
|
||||
* @param error_handler The handler to be called when an error occurs or when
|
||||
* the function completes successfully. Copies will be made of the handler as
|
||||
* required. The equivalent function signature of the handler must be:
|
||||
* @param error_handler The handler to be called when an error occurs. Copies
|
||||
* will be made of the handler as required. The equivalent function signature
|
||||
* of the handler must be:
|
||||
* @code void error_handler(
|
||||
* const asio::socket_error& error // Result of operation
|
||||
* ); @endcode
|
||||
@ -255,9 +255,9 @@ public:
|
||||
*
|
||||
* @param option The option value to be obtained from the acceptor.
|
||||
*
|
||||
* @param error_handler The handler to be called when an error occurs or when
|
||||
* the function completes successfully. Copies will be made of the handler as
|
||||
* required. The equivalent function signature of the handler must be:
|
||||
* @param error_handler The handler to be called when an error occurs. Copies
|
||||
* will be made of the handler as required. The equivalent function signature
|
||||
* of the handler must be:
|
||||
* @code void error_handler(
|
||||
* const asio::socket_error& error // Result of operation
|
||||
* ); @endcode
|
||||
@ -295,9 +295,9 @@ public:
|
||||
* @param peer_socket The stream socket into which the new connection will be
|
||||
* accepted.
|
||||
*
|
||||
* @param error_handler The handler to be called when an error occurs or when
|
||||
* the function completes successfully. Copies will be made of the handler as
|
||||
* required. The equivalent function signature of the handler must be:
|
||||
* @param error_handler The handler to be called when an error occurs. Copies
|
||||
* will be made of the handler as required. The equivalent function signature
|
||||
* of the handler must be:
|
||||
* @code void error_handler(
|
||||
* const asio::socket_error& error // Result of operation
|
||||
* ); @endcode
|
||||
@ -394,9 +394,9 @@ public:
|
||||
* @param peer_address An address object which will receive the network
|
||||
* address of the remote peer.
|
||||
*
|
||||
* @param error_handler The handler to be called when an error occurs or when
|
||||
* the function completes successfully. Copies will be made of the handler as
|
||||
* required. The equivalent function signature of the handler must be:
|
||||
* @param error_handler The handler to be called when an error occurs. Copies
|
||||
* will be made of the handler as required. The equivalent function signature
|
||||
* of the handler must be:
|
||||
* @code void error_handler(
|
||||
* const asio::socket_error& error // Result of operation
|
||||
* ); @endcode
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/error_handler.hpp"
|
||||
#include "asio/null_completion_context.hpp"
|
||||
#include "asio/service_factory.hpp"
|
||||
|
||||
@ -131,7 +132,34 @@ public:
|
||||
template <typename Stream, typename Address>
|
||||
void connect(Stream& peer_socket, const Address& peer_address)
|
||||
{
|
||||
service_.connect(impl_, peer_socket.lowest_layer(), peer_address);
|
||||
service_.connect(impl_, peer_socket.lowest_layer(), peer_address,
|
||||
default_error_handler());
|
||||
}
|
||||
|
||||
/// Connect a stream socket to the peer at the specified address.
|
||||
/**
|
||||
* This function is used to connect a stream socket to the specified remote
|
||||
* address. The function call will block until the connection is successfully
|
||||
* made or an error occurs.
|
||||
*
|
||||
* @param peer_socket The stream socket to be connected.
|
||||
*
|
||||
* @param peer_address The remote address of the peer to which the socket
|
||||
* will be connected.
|
||||
*
|
||||
* @param error_handler The handler to be called when an error occurs. Copies
|
||||
* will be made of the handler as required. The equivalent function signature
|
||||
* of the handler must be:
|
||||
* @code void error_handler(
|
||||
* const asio::socket_error& error // Result of operation
|
||||
* ); @endcode
|
||||
*/
|
||||
template <typename Stream, typename Address, typename Error_Handler>
|
||||
void connect(Stream& peer_socket, const Address& peer_address,
|
||||
Error_Handler error_handler)
|
||||
{
|
||||
service_.connect(impl_, peer_socket.lowest_layer(), peer_address,
|
||||
error_handler);
|
||||
}
|
||||
|
||||
/// Start an asynchronous connect.
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/error_handler.hpp"
|
||||
#include "asio/null_completion_context.hpp"
|
||||
#include "asio/service_factory.hpp"
|
||||
|
||||
@ -139,7 +140,26 @@ public:
|
||||
template <typename Option>
|
||||
void set_option(const Option& option)
|
||||
{
|
||||
service_.set_option(impl_, option);
|
||||
service_.set_option(impl_, option, default_error_handler());
|
||||
}
|
||||
|
||||
/// Set an option on the socket.
|
||||
/**
|
||||
* This function is used to set an option on the socket.
|
||||
*
|
||||
* @param option The new option value to be set on the socket.
|
||||
*
|
||||
* @param error_handler The handler to be called when an error occurs. Copies
|
||||
* will be made of the handler as required. The equivalent function signature
|
||||
* of the handler must be:
|
||||
* @code void error_handler(
|
||||
* const asio::socket_error& error // Result of operation
|
||||
* ); @endcode
|
||||
*/
|
||||
template <typename Option, typename Error_Handler>
|
||||
void set_option(const Option& option, Error_Handler error_handler)
|
||||
{
|
||||
service_.set_option(impl_, option, error_handler);
|
||||
}
|
||||
|
||||
/// Get an option from the socket.
|
||||
@ -153,7 +173,26 @@ public:
|
||||
template <typename Option>
|
||||
void get_option(Option& option)
|
||||
{
|
||||
service_.get_option(impl_, option);
|
||||
service_.get_option(impl_, option, default_error_handler());
|
||||
}
|
||||
|
||||
/// Get an option from the socket.
|
||||
/**
|
||||
* This function is used to get the current value of an option on the socket.
|
||||
*
|
||||
* @param option The option value to be obtained from the socket.
|
||||
*
|
||||
* @param error_handler The handler to be called when an error occurs. Copies
|
||||
* will be made of the handler as required. The equivalent function signature
|
||||
* of the handler must be:
|
||||
* @code void error_handler(
|
||||
* const asio::socket_error& error // Result of operation
|
||||
* ); @endcode
|
||||
*/
|
||||
template <typename Option, typename Error_Handler>
|
||||
void get_option(Option& option, Error_Handler error_handler)
|
||||
{
|
||||
service_.get_option(impl_, option, error_handler);
|
||||
}
|
||||
|
||||
/// Send the given data to the peer.
|
||||
@ -177,7 +216,37 @@ public:
|
||||
*/
|
||||
size_t send(const void* data, size_t length)
|
||||
{
|
||||
return service_.send(impl_, data, length);
|
||||
return service_.send(impl_, data, length, default_error_handler());
|
||||
}
|
||||
|
||||
/// Send the given data to the peer.
|
||||
/**
|
||||
* This function is used to send data to the stream socket's peer. The
|
||||
* function call will block until the data has been sent successfully or an
|
||||
* error occurs.
|
||||
*
|
||||
* @param data The data to be sent to remote peer.
|
||||
*
|
||||
* @param length The size of the data to be sent, in bytes.
|
||||
*
|
||||
* @param error_handler The handler to be called when an error occurs. Copies
|
||||
* will be made of the handler as required. The equivalent function signature
|
||||
* of the handler must be:
|
||||
* @code void error_handler(
|
||||
* const asio::socket_error& error // Result of operation
|
||||
* ); @endcode
|
||||
*
|
||||
* @returns The number of bytes sent or 0 if the connection was closed
|
||||
* cleanly.
|
||||
*
|
||||
* @note The send operation may not transmit all of the data to the peer.
|
||||
* Consider using the asio::send_n() function if you need to ensure that all
|
||||
* data is sent before the blocking operation completes.
|
||||
*/
|
||||
template <typename Error_Handler>
|
||||
size_t send(const void* data, size_t length, Error_Handler error_handler)
|
||||
{
|
||||
return service_.send(impl_, data, length, error_handler);
|
||||
}
|
||||
|
||||
/// Start an asynchronous send.
|
||||
@ -267,7 +336,38 @@ public:
|
||||
*/
|
||||
size_t recv(void* data, size_t max_length)
|
||||
{
|
||||
return service_.recv(impl_, data, max_length);
|
||||
return service_.recv(impl_, data, max_length, default_error_handler());
|
||||
}
|
||||
|
||||
/// Receive some data from the peer.
|
||||
/**
|
||||
* This function is used to receive data from the stream socket's peer. The
|
||||
* function call will block until data has received successfully or an error
|
||||
* occurs.
|
||||
*
|
||||
* @param data The buffer into which the received data will be written.
|
||||
*
|
||||
* @param max_length The maximum size of the data to be received, in bytes.
|
||||
*
|
||||
* @param error_handler The handler to be called when an error occurs. Copies
|
||||
* will be made of the handler as required. The equivalent function signature
|
||||
* of the handler must be:
|
||||
* @code void error_handler(
|
||||
* const asio::socket_error& error // Result of operation
|
||||
* ); @endcode
|
||||
*
|
||||
* @returns The number of bytes received or 0 if the connection was closed
|
||||
* cleanly.
|
||||
*
|
||||
* @note The recv operation may not receive all of the requested number of
|
||||
* bytes. Consider using the asio::recv_n() function if you need to ensure
|
||||
* that the requested amount of data is received before the blocking
|
||||
* operation completes.
|
||||
*/
|
||||
template <typename Error_Handler>
|
||||
size_t recv(void* data, size_t max_length, Error_Handler error_handler)
|
||||
{
|
||||
return service_.recv(impl_, data, max_length, error_handler);
|
||||
}
|
||||
|
||||
/// Start an asynchronous receive.
|
||||
|
@ -94,6 +94,14 @@ public:
|
||||
return next_layer_.send(data, length);
|
||||
}
|
||||
|
||||
/// Send the given data to the peer. Returns the number of bytes sent or 0 if
|
||||
/// the stream was closed cleanly.
|
||||
template <typename Error_Handler>
|
||||
size_t send(const void* data, size_t length, Error_Handler error_handler)
|
||||
{
|
||||
return next_layer_.send(data, length, error_handler);
|
||||
}
|
||||
|
||||
/// Start an asynchronous send. The data being sent must be valid for the
|
||||
/// lifetime of the asynchronous operation.
|
||||
template <typename Handler>
|
||||
@ -125,6 +133,22 @@ public:
|
||||
return buffer_.size() - previous_size;
|
||||
}
|
||||
|
||||
/// Fill the buffer with some data. Returns the number of bytes placed in the
|
||||
/// buffer as a result of the operation, or 0 if the underlying connection
|
||||
/// was closed.
|
||||
template <typename Error_Handler>
|
||||
size_t fill(Error_Handler error_handler)
|
||||
{
|
||||
detail::buffer_resize_guard<Buffer> resize_guard(buffer_);
|
||||
size_t previous_size = buffer_.size();
|
||||
buffer_.resize(buffer_.capacity());
|
||||
buffer_.resize(previous_size + next_layer_.recv(
|
||||
buffer_.begin() + previous_size, buffer_.size() - previous_size,
|
||||
error_handler));
|
||||
resize_guard.commit();
|
||||
return buffer_.size() - previous_size;
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
class fill_handler
|
||||
{
|
||||
@ -180,6 +204,16 @@ public:
|
||||
return copy(data, max_length);
|
||||
}
|
||||
|
||||
/// Receive some data from the peer. Returns the number of bytes received or
|
||||
/// 0 if the stream was closed cleanly.
|
||||
template <typename Error_Handler>
|
||||
size_t recv(void* data, size_t max_length, Error_Handler error_handler)
|
||||
{
|
||||
if (buffer_.empty() && !fill(error_handler))
|
||||
return 0;
|
||||
return copy(data, max_length);
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
class recv_handler
|
||||
{
|
||||
|
@ -80,6 +80,14 @@ public:
|
||||
return next_layer_.send(data, length);
|
||||
}
|
||||
|
||||
/// Send the given data to the peer. Returns the number of bytes sent or 0 if
|
||||
/// the stream was closed cleanly.
|
||||
template <typename Error_Handler>
|
||||
size_t send(const void* data, size_t length, Error_Handler error_handler)
|
||||
{
|
||||
return next_layer_.send(data, length, error_handler);
|
||||
}
|
||||
|
||||
/// Start an asynchronous send. The data being sent must be valid for the
|
||||
/// lifetime of the asynchronous operation.
|
||||
template <typename Handler>
|
||||
@ -104,6 +112,14 @@ public:
|
||||
return next_layer_.recv(data, max_length);
|
||||
}
|
||||
|
||||
/// Receive some data from the peer. Returns the number of bytes received or
|
||||
/// 0 if the stream was closed cleanly.
|
||||
template <typename Error_Handler>
|
||||
size_t recv(void* data, size_t max_length, Error_Handler error_handler)
|
||||
{
|
||||
return next_layer_.recv(data, max_length, error_handler);
|
||||
}
|
||||
|
||||
/// Start an asynchronous receive. The buffer for the data being received
|
||||
/// must be valid for the lifetime of the asynchronous operation.
|
||||
template <typename Handler>
|
||||
|
@ -90,6 +90,14 @@ public:
|
||||
return stream_impl_.send(data, length);
|
||||
}
|
||||
|
||||
/// Send the given data to the peer. Returns the number of bytes sent or 0 if
|
||||
/// the stream was closed cleanly.
|
||||
template <typename Error_Handler>
|
||||
size_t send(const void* data, size_t length, Error_Handler error_handler)
|
||||
{
|
||||
return stream_impl_.send(data, length, error_handler);
|
||||
}
|
||||
|
||||
/// Start an asynchronous send. The data being sent must be valid for the
|
||||
/// lifetime of the asynchronous operation.
|
||||
template <typename Handler>
|
||||
@ -115,6 +123,15 @@ public:
|
||||
return stream_impl_.fill();
|
||||
}
|
||||
|
||||
/// Fill the buffer with some data. Returns the number of bytes placed in the
|
||||
/// buffer as a result of the operation, or 0 if the underlying connection
|
||||
/// was closed.
|
||||
template <typename Error_Handler>
|
||||
size_t fill(Error_Handler error_handler)
|
||||
{
|
||||
return stream_impl_.fill(error_handler);
|
||||
}
|
||||
|
||||
/// Start an asynchronous fill.
|
||||
template <typename Handler>
|
||||
void async_fill(Handler handler)
|
||||
@ -136,6 +153,14 @@ public:
|
||||
return stream_impl_.recv(data, max_length);
|
||||
}
|
||||
|
||||
/// Receive some data from the peer. Returns the number of bytes received or
|
||||
/// 0 if the stream was closed cleanly.
|
||||
template <typename Error_Handler>
|
||||
size_t recv(void* data, size_t max_length, Error_Handler error_handler)
|
||||
{
|
||||
return stream_impl_.recv(data, max_length, error_handler);
|
||||
}
|
||||
|
||||
/// Start an asynchronous receive. The buffer for the data being received
|
||||
/// must be valid for the lifetime of the asynchronous operation.
|
||||
template <typename Handler>
|
||||
|
@ -82,8 +82,6 @@ public:
|
||||
}
|
||||
|
||||
impl = sock.release();
|
||||
|
||||
error_handler(socket_error(socket_error::success));
|
||||
}
|
||||
|
||||
// Destroy a dgram socket implementation.
|
||||
@ -103,12 +101,7 @@ public:
|
||||
{
|
||||
if (socket_ops::setsockopt(impl, option.level(), option.name(),
|
||||
option.data(), option.size()))
|
||||
{
|
||||
error_handler(socket_error(socket_ops::get_error()));
|
||||
return;
|
||||
}
|
||||
|
||||
error_handler(socket_error(socket_error::success));
|
||||
}
|
||||
|
||||
// Set a socket option.
|
||||
@ -118,12 +111,7 @@ public:
|
||||
socket_len_type size = option.size();
|
||||
if (socket_ops::getsockopt(impl, option.level(), option.name(),
|
||||
option.data(), &size))
|
||||
{
|
||||
error_handler(socket_error(socket_ops::get_error()));
|
||||
return;
|
||||
}
|
||||
|
||||
error_handler(socket_error(socket_error::success));
|
||||
}
|
||||
|
||||
// Send a datagram to the specified address. Returns the number of bytes
|
||||
@ -139,8 +127,6 @@ public:
|
||||
error_handler(socket_error(socket_ops::get_error()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
error_handler(socket_error(socket_error::success));
|
||||
return bytes_sent;
|
||||
}
|
||||
|
||||
@ -217,8 +203,6 @@ public:
|
||||
|
||||
sender_address.native_size(addr_len);
|
||||
|
||||
error_handler(socket_error(socket_error::success));
|
||||
|
||||
return bytes_recvd;
|
||||
}
|
||||
|
||||
|
@ -92,8 +92,6 @@ public:
|
||||
}
|
||||
|
||||
impl = sock.release();
|
||||
|
||||
error_handler(socket_error(socket_error::success));
|
||||
}
|
||||
|
||||
// Destroy a stream socket implementation.
|
||||
@ -113,12 +111,7 @@ public:
|
||||
{
|
||||
if (socket_ops::setsockopt(impl, option.level(), option.name(),
|
||||
option.data(), option.size()))
|
||||
{
|
||||
error_handler(socket_error(socket_ops::get_error()));
|
||||
return;
|
||||
}
|
||||
|
||||
error_handler(socket_error(socket_error::success));
|
||||
}
|
||||
|
||||
// Set a socket option.
|
||||
@ -128,12 +121,7 @@ public:
|
||||
socket_len_type size = option.size();
|
||||
if (socket_ops::getsockopt(impl, option.level(), option.name(),
|
||||
option.data(), &size))
|
||||
{
|
||||
error_handler(socket_error(socket_ops::get_error()));
|
||||
return;
|
||||
}
|
||||
|
||||
error_handler(socket_error(socket_error::success));
|
||||
}
|
||||
|
||||
// Accept a new connection.
|
||||
@ -157,8 +145,6 @@ public:
|
||||
}
|
||||
|
||||
peer.set_impl(new_socket);
|
||||
|
||||
error_handler(socket_error(socket_error::success));
|
||||
}
|
||||
|
||||
// Accept a new connection.
|
||||
@ -187,8 +173,6 @@ public:
|
||||
peer_address.native_size(addr_len);
|
||||
|
||||
peer.set_impl(new_socket);
|
||||
|
||||
error_handler(socket_error(socket_error::success));
|
||||
}
|
||||
|
||||
template <typename Stream_Socket_Service, typename Handler,
|
||||
|
@ -119,23 +119,29 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
// Connect the given socket to the peer at the specified address. Throws a
|
||||
// socket_error exception on error.
|
||||
template <typename Stream_Socket_Service, typename Address>
|
||||
// Connect the given socket to the peer at the specified address.
|
||||
template <typename Stream_Socket_Service, typename Address,
|
||||
typename Error_Handler>
|
||||
void connect(impl_type& impl,
|
||||
basic_stream_socket<Stream_Socket_Service>& peer,
|
||||
const Address& peer_address)
|
||||
const Address& peer_address, Error_Handler error_handler)
|
||||
{
|
||||
// We cannot connect a socket that is already open.
|
||||
if (peer.impl() != invalid_socket)
|
||||
throw socket_error(socket_error::already_connected);
|
||||
{
|
||||
error_handler(socket_error(socket_error::already_connected));
|
||||
return;
|
||||
}
|
||||
|
||||
// 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)
|
||||
throw socket_error(socket_ops::get_error());
|
||||
{
|
||||
error_handler(socket_error(socket_ops::get_error()));
|
||||
return;
|
||||
}
|
||||
|
||||
// Perform the connect operation itself.
|
||||
impl->add_socket(sock.get());
|
||||
@ -143,7 +149,10 @@ public:
|
||||
peer_address.native_size());
|
||||
impl->remove_socket(sock.get());
|
||||
if (result == socket_error_retval)
|
||||
throw socket_error(socket_ops::get_error());
|
||||
{
|
||||
error_handler(socket_error(socket_ops::get_error()));
|
||||
return;
|
||||
}
|
||||
|
||||
// Connection was successful. The stream_socket object will now take
|
||||
// ownership of the newly connected native socket handle.
|
||||
|
@ -72,33 +72,38 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
// Set a socket option. Throws a socket_error exception on failure.
|
||||
template <typename Option>
|
||||
void set_option(impl_type& impl, const Option& option)
|
||||
// Set a socket option.
|
||||
template <typename Option, typename Error_Handler>
|
||||
void set_option(impl_type& impl, const Option& option,
|
||||
Error_Handler error_handler)
|
||||
{
|
||||
if (socket_ops::setsockopt(impl, option.level(), option.name(),
|
||||
option.data(), option.size()))
|
||||
throw socket_error(socket_ops::get_error());
|
||||
error_handler(socket_error(socket_ops::get_error()));
|
||||
}
|
||||
|
||||
// Set a socket option. Throws a socket_error exception on failure.
|
||||
template <typename Option>
|
||||
void get_option(impl_type& impl, Option& option)
|
||||
// Set a socket option.
|
||||
template <typename Option, typename Error_Handler>
|
||||
void get_option(impl_type& impl, Option& option, Error_Handler error_handler)
|
||||
{
|
||||
socket_len_type size = option.size();
|
||||
if (socket_ops::getsockopt(impl, option.level(), option.name(),
|
||||
option.data(), &size))
|
||||
throw socket_error(socket_ops::get_error());
|
||||
error_handler(socket_error(socket_ops::get_error()));
|
||||
}
|
||||
|
||||
// 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)
|
||||
// 0 if the connection was closed cleanly.
|
||||
template <typename Error_Handler>
|
||||
size_t send(impl_type& impl, const void* data, size_t length,
|
||||
Error_Handler error_handler)
|
||||
{
|
||||
int bytes_sent = socket_ops::send(impl, data, length, 0);
|
||||
if (bytes_sent < 0)
|
||||
throw socket_error(socket_ops::get_error());
|
||||
{
|
||||
error_handler(socket_error(socket_ops::get_error()));
|
||||
return 0;
|
||||
}
|
||||
return bytes_sent;
|
||||
}
|
||||
|
||||
@ -154,13 +159,17 @@ public:
|
||||
}
|
||||
|
||||
// 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)
|
||||
// 0 if the connection was closed cleanly.
|
||||
template <typename Error_Handler>
|
||||
size_t recv(impl_type& impl, void* data, size_t max_length,
|
||||
Error_Handler error_handler)
|
||||
{
|
||||
int bytes_recvd = socket_ops::recv(impl, data, max_length, 0);
|
||||
if (bytes_recvd < 0)
|
||||
throw socket_error(socket_ops::get_error());
|
||||
{
|
||||
error_handler(socket_error(socket_ops::get_error()));
|
||||
return 0;
|
||||
}
|
||||
return bytes_recvd;
|
||||
}
|
||||
|
||||
|
@ -78,33 +78,49 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
// Set a socket option. Throws a socket_error exception on failure.
|
||||
template <typename Option>
|
||||
void set_option(impl_type& impl, const Option& option)
|
||||
// Set a socket option.
|
||||
template <typename Option, typename Error_Handler>
|
||||
void set_option(impl_type& impl, const Option& option,
|
||||
Error_Handler error_handler)
|
||||
{
|
||||
if (socket_ops::setsockopt(impl, option.level(), option.name(),
|
||||
option.data(), option.size()))
|
||||
throw socket_error(socket_ops::get_error());
|
||||
{
|
||||
error_handler(socket_error(socket_ops::get_error()));
|
||||
return;
|
||||
}
|
||||
|
||||
error_handler(socket_error(socket_error::success));
|
||||
}
|
||||
|
||||
// Set a socket option. Throws a socket_error exception on failure.
|
||||
template <typename Option>
|
||||
void get_option(impl_type& impl, Option& option)
|
||||
// Set a socket option.
|
||||
template <typename Option, typename Error_Handler>
|
||||
void get_option(impl_type& impl, Option& option, Error_Handler error_handler)
|
||||
{
|
||||
socket_len_type size = option.size();
|
||||
if (socket_ops::getsockopt(impl, option.level(), option.name(),
|
||||
option.data(), &size))
|
||||
throw socket_error(socket_ops::get_error());
|
||||
{
|
||||
error_handler(socket_error(socket_ops::get_error()));
|
||||
return;
|
||||
}
|
||||
|
||||
error_handler(socket_error(socket_error::success));
|
||||
}
|
||||
|
||||
// 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)
|
||||
// 0 if the connection was closed cleanly.
|
||||
template <typename Error_Handler>
|
||||
size_t send(impl_type& impl, const void* data, size_t length,
|
||||
Error_Handler error_handler)
|
||||
{
|
||||
int bytes_sent = socket_ops::send(impl, data, length, 0);
|
||||
if (bytes_sent < 0)
|
||||
throw socket_error(socket_ops::get_error());
|
||||
{
|
||||
error_handler(socket_error(socket_ops::get_error()));
|
||||
return 0;
|
||||
}
|
||||
error_handler(socket_error(socket_error::success));
|
||||
return bytes_sent;
|
||||
}
|
||||
|
||||
@ -178,13 +194,18 @@ public:
|
||||
}
|
||||
|
||||
// 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)
|
||||
// 0 if the connection was closed cleanly.
|
||||
template <typename Error_Handler>
|
||||
size_t recv(impl_type& impl, void* data, size_t max_length,
|
||||
Error_Handler error_handler)
|
||||
{
|
||||
int bytes_recvd = socket_ops::recv(impl, data, max_length, 0);
|
||||
if (bytes_recvd < 0)
|
||||
throw socket_error(socket_ops::get_error());
|
||||
{
|
||||
error_handler(socket_error(socket_ops::get_error()));
|
||||
return 0;
|
||||
}
|
||||
error_handler(socket_error(socket_error::success));
|
||||
return bytes_recvd;
|
||||
}
|
||||
|
||||
|
@ -37,28 +37,28 @@ class expression
|
||||
{
|
||||
public:
|
||||
/// Constructor.
|
||||
explicit expression(Expr expr)
|
||||
explicit expression(Expr expr)
|
||||
: expr_(expr)
|
||||
{
|
||||
}
|
||||
|
||||
/// Evaluate the expression.
|
||||
template <typename Error>
|
||||
bool operator()(const Error& err)
|
||||
bool operator()(const Error& err)
|
||||
{
|
||||
return expr_(err);
|
||||
}
|
||||
|
||||
private:
|
||||
/// The contained expression.
|
||||
Expr expr_;
|
||||
Expr expr_;
|
||||
};
|
||||
|
||||
/// Create an expression object using template type deduction.
|
||||
template <typename Expr>
|
||||
expression<Expr> make_expression(Expr expr)
|
||||
{
|
||||
return expression<Expr>(expr);
|
||||
return expression<Expr>(expr);
|
||||
}
|
||||
|
||||
/// Class template to compare the error for equality with a given value.
|
||||
@ -67,35 +67,35 @@ class value_eq_error
|
||||
{
|
||||
public:
|
||||
/// Constructor.
|
||||
explicit value_eq_error(Value value)
|
||||
explicit value_eq_error(Value value)
|
||||
: value_(value)
|
||||
{
|
||||
}
|
||||
|
||||
/// Evaluate the expression.
|
||||
template <typename Error>
|
||||
bool operator()(const Error& err)
|
||||
bool operator()(const Error& err)
|
||||
{
|
||||
return value_ == err;
|
||||
}
|
||||
|
||||
private:
|
||||
/// The value to compare the error against.
|
||||
Value value_;
|
||||
Value value_;
|
||||
};
|
||||
|
||||
/// Compare the error for equality with a given value.
|
||||
template <typename Value>
|
||||
expression<value_eq_error<Value> > operator==(Value value, error_t)
|
||||
{
|
||||
return make_expression(value_eq_error<Value>(value));
|
||||
return make_expression(value_eq_error<Value>(value));
|
||||
}
|
||||
|
||||
/// Compare the error for equality with a given value.
|
||||
template <typename Value>
|
||||
expression<value_eq_error<Value> > operator==(error_t, Value value)
|
||||
{
|
||||
return make_expression(value_eq_error<Value>(value));
|
||||
return make_expression(value_eq_error<Value>(value));
|
||||
}
|
||||
|
||||
/// Class template to compare the error for inequality with a given value.
|
||||
@ -104,35 +104,35 @@ class value_neq_error
|
||||
{
|
||||
public:
|
||||
/// Constructor.
|
||||
explicit value_neq_error(Value value)
|
||||
explicit value_neq_error(Value value)
|
||||
: value_(value)
|
||||
{
|
||||
}
|
||||
|
||||
/// Evaluate the expression.
|
||||
template <typename Error>
|
||||
bool operator()(const Error& err)
|
||||
bool operator()(const Error& err)
|
||||
{
|
||||
return value_ != err;
|
||||
}
|
||||
|
||||
private:
|
||||
/// The value to compare the error against.
|
||||
Value value_;
|
||||
Value value_;
|
||||
};
|
||||
|
||||
/// Compare the error for inequality with a given value.
|
||||
template <typename Value>
|
||||
expression<value_neq_error<Value> > operator!=(Value value, error_t)
|
||||
{
|
||||
return make_expression(value_neq_error<Value>(value));
|
||||
return make_expression(value_neq_error<Value>(value));
|
||||
}
|
||||
|
||||
/// Compare the error for inequality with a given value.
|
||||
template <typename Value>
|
||||
expression<value_neq_error<Value> > operator!=(error_t, Value value)
|
||||
{
|
||||
return make_expression(value_neq_error<Value>(value));
|
||||
return make_expression(value_neq_error<Value>(value));
|
||||
}
|
||||
|
||||
/// Class template to perform logical or on two expressions.
|
||||
@ -141,7 +141,7 @@ class expr_or_expr
|
||||
{
|
||||
public:
|
||||
/// Constructor.
|
||||
explicit expr_or_expr(Expr1 expr1, Expr2 expr2)
|
||||
explicit expr_or_expr(Expr1 expr1, Expr2 expr2)
|
||||
: expr1_(expr1),
|
||||
expr2_(expr2)
|
||||
{
|
||||
@ -149,17 +149,17 @@ public:
|
||||
|
||||
// Evaluate the expression.
|
||||
template <typename Error>
|
||||
bool operator()(const Error& err)
|
||||
bool operator()(const Error& err)
|
||||
{
|
||||
return expr1_(err) || expr2_(err);
|
||||
}
|
||||
|
||||
private:
|
||||
/// The first expression to be included in the logical or.
|
||||
Expr1 expr1_;
|
||||
Expr1 expr1_;
|
||||
|
||||
/// The second expression to be included in the logical or.
|
||||
Expr2 expr2_;
|
||||
Expr2 expr2_;
|
||||
};
|
||||
|
||||
/// Perform a logical or on two expressions.
|
||||
@ -167,7 +167,7 @@ template <typename Expr1, typename Expr2>
|
||||
expression<expr_or_expr<expression<Expr1>, expression<Expr2> > >
|
||||
operator||(expression<Expr1> expr1, expression<Expr2> expr2)
|
||||
{
|
||||
return make_expression(
|
||||
return make_expression(
|
||||
expr_or_expr<expression<Expr1>, expression<Expr2> >(expr1, expr2));
|
||||
}
|
||||
|
||||
@ -177,7 +177,7 @@ class expr_and_expr
|
||||
{
|
||||
public:
|
||||
/// Constructor.
|
||||
explicit expr_and_expr(Expr1 expr1, Expr2 expr2)
|
||||
explicit expr_and_expr(Expr1 expr1, Expr2 expr2)
|
||||
: expr1_(expr1),
|
||||
expr2_(expr2)
|
||||
{
|
||||
@ -185,17 +185,17 @@ public:
|
||||
|
||||
// Evaluate the expression.
|
||||
template <typename Error>
|
||||
bool operator()(const Error& err)
|
||||
bool operator()(const Error& err)
|
||||
{
|
||||
return expr1_(err) && expr2_(err);
|
||||
}
|
||||
|
||||
private:
|
||||
/// The first expression to be included in the logical and.
|
||||
Expr1 expr1_;
|
||||
Expr1 expr1_;
|
||||
|
||||
/// The second expression to be included in the logical and.
|
||||
Expr2 expr2_;
|
||||
Expr2 expr2_;
|
||||
};
|
||||
|
||||
/// Perform a logical and on two expressions.
|
||||
@ -203,7 +203,7 @@ template <typename Expr1, typename Expr2>
|
||||
expression<expr_and_expr<expression<Expr1>, expression<Expr2> > >
|
||||
operator&&(expression<Expr1> expr1, expression<Expr2> expr2)
|
||||
{
|
||||
return make_expression(
|
||||
return make_expression(
|
||||
expr_and_expr<expression<Expr1>, expression<Expr2> >(expr1, expr2));
|
||||
}
|
||||
|
||||
@ -213,7 +213,7 @@ class throw_error
|
||||
public:
|
||||
/// Evaluate the expression.
|
||||
template <typename Error>
|
||||
bool operator()(const Error& err)
|
||||
bool operator()(const Error& err)
|
||||
{
|
||||
throw err;
|
||||
}
|
||||
@ -225,14 +225,14 @@ class throw_error_if_t
|
||||
{
|
||||
public:
|
||||
/// Constructor.
|
||||
throw_error_if_t(Expr expr)
|
||||
throw_error_if_t(Expr expr)
|
||||
: expr_(expr)
|
||||
{
|
||||
}
|
||||
|
||||
/// Evaluate the expression.
|
||||
template <typename Error>
|
||||
bool operator()(const Error& err)
|
||||
bool operator()(const Error& err)
|
||||
{
|
||||
if (expr_(err))
|
||||
throw err;
|
||||
@ -241,14 +241,14 @@ public:
|
||||
|
||||
private:
|
||||
/// The expression which, if true, will result in the error being thrown.
|
||||
Expr expr_;
|
||||
Expr expr_;
|
||||
};
|
||||
|
||||
/// Throw an error if an expression is true.
|
||||
template <typename Expr>
|
||||
expression<throw_error_if_t<Expr> > throw_error_if(Expr expr)
|
||||
{
|
||||
return make_expression(throw_error_if_t<Expr>(expr));
|
||||
return make_expression(throw_error_if_t<Expr>(expr));
|
||||
}
|
||||
|
||||
/// Class template to always set a variable to the error.
|
||||
@ -264,7 +264,7 @@ public:
|
||||
|
||||
/// Evaluate the expression.
|
||||
template <typename Error>
|
||||
bool operator()(const Error& err)
|
||||
bool operator()(const Error& err)
|
||||
{
|
||||
target_ = err;
|
||||
return true;
|
||||
@ -279,7 +279,9 @@ private:
|
||||
template <typename Target>
|
||||
expression<set_error_t<Target> > set_error(Target& target)
|
||||
{
|
||||
return make_expression(set_error_t<Target>(target));
|
||||
if (target)
|
||||
target = Target();
|
||||
return make_expression(set_error_t<Target>(target));
|
||||
}
|
||||
|
||||
/// Class template to set a variable to the error if an expression is true.
|
||||
@ -288,7 +290,7 @@ class set_error_if_t
|
||||
{
|
||||
public:
|
||||
/// Constructor.
|
||||
set_error_if_t(Target& target, Expr expr)
|
||||
set_error_if_t(Target& target, Expr expr)
|
||||
: target_(target),
|
||||
expr_(expr)
|
||||
{
|
||||
@ -296,7 +298,7 @@ public:
|
||||
|
||||
/// Evaluate the expression.
|
||||
template <typename Error>
|
||||
bool operator()(const Error& err)
|
||||
bool operator()(const Error& err)
|
||||
{
|
||||
if (expr_(err))
|
||||
{
|
||||
@ -311,7 +313,7 @@ private:
|
||||
Target& target_;
|
||||
|
||||
/// The expression which, if true, will result in the variable being set.
|
||||
Expr expr_;
|
||||
Expr expr_;
|
||||
};
|
||||
|
||||
/// Set a variable to the error if an expression is true.
|
||||
@ -319,7 +321,9 @@ template <typename Target, typename Expr>
|
||||
expression<set_error_if_t<Target, Expr> >
|
||||
set_error_if(Target& target, Expr expr)
|
||||
{
|
||||
return make_expression(set_error_if_t<Target, Expr>(target, expr));
|
||||
if (target)
|
||||
target = Target();
|
||||
return make_expression(set_error_if_t<Target, Expr>(target, expr));
|
||||
}
|
||||
|
||||
/// Class template to always log an error to a stream.
|
||||
@ -335,7 +339,7 @@ public:
|
||||
|
||||
/// Evaluate the expression.
|
||||
template <typename Error>
|
||||
bool operator()(const Error& err)
|
||||
bool operator()(const Error& err)
|
||||
{
|
||||
ostream_ << err << "\n";
|
||||
return true;
|
||||
@ -350,7 +354,7 @@ private:
|
||||
template <typename Ostream>
|
||||
expression<log_error_t<Ostream> > log_error(Ostream& ostream)
|
||||
{
|
||||
return make_expression(log_error_t<Ostream>(ostream));
|
||||
return make_expression(log_error_t<Ostream>(ostream));
|
||||
}
|
||||
|
||||
/// Class template to set a variable to the error if an expression is true.
|
||||
@ -359,7 +363,7 @@ class log_error_if_t
|
||||
{
|
||||
public:
|
||||
/// Constructor.
|
||||
log_error_if_t(Ostream& ostream, Expr expr)
|
||||
log_error_if_t(Ostream& ostream, Expr expr)
|
||||
: ostream_(ostream),
|
||||
expr_(expr)
|
||||
{
|
||||
@ -367,7 +371,7 @@ public:
|
||||
|
||||
/// Evaluate the expression.
|
||||
template <typename Error>
|
||||
bool operator()(const Error& err)
|
||||
bool operator()(const Error& err)
|
||||
{
|
||||
if (expr_(err))
|
||||
{
|
||||
@ -382,7 +386,7 @@ private:
|
||||
Ostream& ostream_;
|
||||
|
||||
/// The expression which, if true, will result in the variable being set.
|
||||
Expr expr_;
|
||||
Expr expr_;
|
||||
};
|
||||
|
||||
/// Set a variable to the error if an expression is true.
|
||||
@ -390,7 +394,7 @@ template <typename Ostream, typename Expr>
|
||||
expression<log_error_if_t<Ostream, Expr> >
|
||||
log_error_if(Ostream& ostream, Expr expr)
|
||||
{
|
||||
return make_expression(log_error_if_t<Ostream, Expr>(ostream, expr));
|
||||
return make_expression(log_error_if_t<Ostream, Expr>(ostream, expr));
|
||||
}
|
||||
|
||||
/// The default error handler.
|
||||
|
@ -54,6 +54,41 @@ size_t recv(Stream& s, void* data, size_t max_length)
|
||||
return s.recv(data, max_length);
|
||||
}
|
||||
|
||||
/// Read some data from a stream.
|
||||
/**
|
||||
* This function is used to receive data on a stream. The function call will
|
||||
* block until data has received successfully or an error occurs.
|
||||
*
|
||||
* @param s The stream on which the data is to be received.
|
||||
*
|
||||
* @param data The buffer into which the received data will be written.
|
||||
*
|
||||
* @param max_length The maximum size of the data to be received, in bytes.
|
||||
*
|
||||
* @param error_handler The handler to be called when an error occurs. Copies
|
||||
* will be made of the handler as required. The equivalent function signature
|
||||
* of the handler must be:
|
||||
* @code template <typename Error>
|
||||
* void error_handler(
|
||||
* const Error& error // Result of operation (the actual type is dependent on
|
||||
* // the underlying stream's recv operation)
|
||||
* ); @endcode
|
||||
*
|
||||
* @returns The number of bytes received, or 0 if end-of-file was reached or
|
||||
* the connection was closed cleanly.
|
||||
*
|
||||
* @note The recv operation may not receive all of the requested number of
|
||||
* bytes. Consider using the asio::recv_n() function if you need to ensure that
|
||||
* the requested amount of data is received before the blocking operation
|
||||
* completes.
|
||||
*/
|
||||
template <typename Stream, typename Error_Handler>
|
||||
size_t recv(Stream& s, void* data, size_t max_length,
|
||||
Error_Handler error_handler)
|
||||
{
|
||||
return s.recv(data, max_length, error_handler);
|
||||
}
|
||||
|
||||
/// Start an asynchronous receive.
|
||||
/**
|
||||
* This function is used to asynchronously receive data on a stream. The
|
||||
@ -172,6 +207,56 @@ size_t recv_n(Stream& s, void* data, size_t length,
|
||||
return bytes_recvd;
|
||||
}
|
||||
|
||||
/// Read the specified amount of data from the stream before returning.
|
||||
/**
|
||||
* This function is used to receive an exact number of bytes of data on a
|
||||
* stream. The function call will block until the specified number of bytes has
|
||||
* been received successfully or an error occurs.
|
||||
*
|
||||
* @param s The stream on which the data is to be received.
|
||||
*
|
||||
* @param data The buffer into which the received data will be written.
|
||||
*
|
||||
* @param length The size of the data to be received, in bytes.
|
||||
*
|
||||
* @param total_bytes_recvd An optional output parameter that receives the
|
||||
* total number of bytes actually received.
|
||||
*
|
||||
* @param error_handler The handler to be called when an error occurs. Copies
|
||||
* will be made of the handler as required. The equivalent function signature
|
||||
* of the handler must be:
|
||||
* @code template <typename Error>
|
||||
* void error_handler(
|
||||
* const Error& error // Result of operation (the actual type is dependent on
|
||||
* // the underlying stream's recv operation)
|
||||
* ); @endcode
|
||||
*
|
||||
* @returns The number of bytes received on the last recv, or 0 if end-of-file
|
||||
* was reached or the connection was closed cleanly.
|
||||
*/
|
||||
template <typename Stream, typename Error_Handler>
|
||||
size_t recv_n(Stream& s, void* data, size_t length,
|
||||
size_t* total_bytes_recvd, Error_Handler error_handler)
|
||||
{
|
||||
int bytes_recvd = 0;
|
||||
size_t total_recvd = 0;
|
||||
while (total_recvd < length)
|
||||
{
|
||||
bytes_recvd = recv(s, static_cast<char*>(data) + total_recvd,
|
||||
length - total_recvd, error_handler);
|
||||
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;
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
@ -365,6 +450,75 @@ size_t recv_decode(Buffered_Stream& s, Decoder decoder,
|
||||
}
|
||||
}
|
||||
|
||||
/// Read some data from a stream and decode it.
|
||||
/**
|
||||
* This function is used to receive data on a stream and decode it in a single
|
||||
* operation. The function call will block until the decoder function object
|
||||
* indicates that it has finished.
|
||||
*
|
||||
* @param s The stream on which the data is to be received.
|
||||
*
|
||||
* @param decoder The decoder function object to be called to decode the
|
||||
* received data. The function object is assumed to be stateful. That is, it
|
||||
* may not be given sufficient data in a single invocation to complete
|
||||
* decoding, and is expected to maintain state so that it may resume decoding
|
||||
* when the next piece of data is supplied. Copies will be made of the decoder
|
||||
* function object as required, however with respect to maintaining state it
|
||||
* can rely on the fact that only an up-to-date copy will be used. The
|
||||
* equivalent function signature of the handler must be:
|
||||
* @code std::pair<bool, const char*> decoder(
|
||||
* const char* begin, // Pointer to the beginning of data to be decoded.
|
||||
* const char* end // Pointer to one-past-the-end of data to be decoded.
|
||||
* ); @endcode
|
||||
* The first element of the return value is true if the decoder has finished.
|
||||
* The second element is a pointer to the beginning of the unused portion of
|
||||
* the data.
|
||||
*
|
||||
* @param total_bytes_recvd An optional output parameter that receives the
|
||||
* total number of bytes actually received.
|
||||
*
|
||||
* @param error_handler The handler to be called when an error occurs. Copies
|
||||
* will be made of the handler as required. The equivalent function signature
|
||||
* of the handler must be:
|
||||
* @code template <typename Error>
|
||||
* void error_handler(
|
||||
* const Error& error // Result of operation (the actual type is dependent on
|
||||
* // the underlying stream's recv operation)
|
||||
* ); @endcode
|
||||
*
|
||||
* @returns The number of bytes received on the last recv, or 0 if end-of-file
|
||||
* was reached or the connection was closed cleanly.
|
||||
*/
|
||||
template <typename Buffered_Stream, typename Decoder, typename Error_Handler>
|
||||
size_t recv_decode(Buffered_Stream& s, Decoder decoder,
|
||||
size_t* total_bytes_recvd, Error_Handler error_handler)
|
||||
{
|
||||
size_t total_recvd = 0;
|
||||
for (;;)
|
||||
{
|
||||
if (s.recv_buffer().empty() && s.fill(error_handler) == 0)
|
||||
{
|
||||
if (total_bytes_recvd)
|
||||
*total_bytes_recvd = total_recvd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::pair<bool, const char*> result =
|
||||
decoder(s.recv_buffer().begin(), s.recv_buffer().end());
|
||||
|
||||
size_t bytes_read = result.second - s.recv_buffer().begin();
|
||||
s.recv_buffer().pop(bytes_read);
|
||||
total_recvd += bytes_read;
|
||||
|
||||
if (result.first)
|
||||
{
|
||||
if (total_bytes_recvd)
|
||||
*total_bytes_recvd = total_recvd;
|
||||
return bytes_read;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
@ -641,6 +795,43 @@ size_t recv_until(Buffered_Stream& s, std::string& data,
|
||||
total_bytes_recvd);
|
||||
}
|
||||
|
||||
/// Read data from the stream until a delimiter is reached.
|
||||
/**
|
||||
* This function is used to receive data from the stream into a std::string
|
||||
* object until a specified delimiter is reached. The function call will block
|
||||
* until the delimiter is found or an error occurs.
|
||||
*
|
||||
* @param s The stream on which the data is to be received.
|
||||
*
|
||||
* @param data The std::string object into which the received data will be
|
||||
* written.
|
||||
*
|
||||
* @param delimiter The pattern marking the end of the data to receive.
|
||||
*
|
||||
* @param total_bytes_recvd An optional output parameter that receives the
|
||||
* total number of bytes actually received.
|
||||
*
|
||||
* @param error_handler The handler to be called when an error occurs. Copies
|
||||
* will be made of the handler as required. The equivalent function signature
|
||||
* of the handler must be:
|
||||
* @code template <typename Error>
|
||||
* void error_handler(
|
||||
* const Error& error // Result of operation (the actual type is dependent on
|
||||
* // the underlying stream's recv operation)
|
||||
* ); @endcode
|
||||
*
|
||||
* @returns The number of bytes received on the last recv, or 0 if end-of-file
|
||||
* was reached or the connection was closed cleanly.
|
||||
*/
|
||||
template <typename Buffered_Stream, typename Error_Handler>
|
||||
size_t recv_until(Buffered_Stream& s, std::string& data,
|
||||
const std::string& delimiter, size_t* total_bytes_recvd,
|
||||
Error_Handler error_handler)
|
||||
{
|
||||
return recv_decode(s, detail::recv_until_decoder(data, delimiter),
|
||||
total_bytes_recvd, error_handler);
|
||||
}
|
||||
|
||||
/// Start an asynchronous receive that will not complete until the specified
|
||||
/// delimiter is encountered.
|
||||
/**
|
||||
|
@ -48,6 +48,40 @@ size_t send(Stream& s, const void* data, size_t length)
|
||||
return s.send(data, length);
|
||||
}
|
||||
|
||||
/// Write some data to a stream.
|
||||
/**
|
||||
* This function is used to send data on a stream. The function call will block
|
||||
* until the data has been sent successfully or an error occurs.
|
||||
*
|
||||
* @param s The stream on which the data is to be sent.
|
||||
*
|
||||
* @param data The data to be sent on the stream.
|
||||
*
|
||||
* @param length The size of the data to be sent, in bytes.
|
||||
*
|
||||
* @param error_handler The handler to be called when an error occurs. Copies
|
||||
* will be made of the handler as required. The equivalent function signature
|
||||
* of the handler must be:
|
||||
* @code template <typename Error>
|
||||
* void error_handler(
|
||||
* const Error& error // Result of operation (the actual type is dependent on
|
||||
* // the underlying stream's send operation)
|
||||
* ); @endcode
|
||||
*
|
||||
* @returns The number of bytes sent, or 0 if end-of-file was reached or the
|
||||
* connection was closed cleanly.
|
||||
*
|
||||
* @note The send operation may not transmit all of the data to the peer.
|
||||
* Consider using the asio::send_n() function if you need to ensure that all
|
||||
* data is sent before the blocking operation completes.
|
||||
*/
|
||||
template <typename Stream, typename Error_Handler>
|
||||
size_t send(Stream& s, const void* data, size_t length,
|
||||
Error_Handler error_handler)
|
||||
{
|
||||
return s.send(data, length, error_handler);
|
||||
}
|
||||
|
||||
/// Start an asynchronous send.
|
||||
/**
|
||||
* This function is used to asynchronously send data on a stream. The function
|
||||
@ -164,6 +198,56 @@ size_t send_n(Stream& s, const void* data, size_t length,
|
||||
return bytes_sent;
|
||||
}
|
||||
|
||||
/// Write all of the given data to the stream before returning.
|
||||
/**
|
||||
* This function is used to send an exact number of bytes of data on a stream.
|
||||
* The function call will block until the specified number of bytes has been
|
||||
* sent successfully or an error occurs.
|
||||
*
|
||||
* @param s The stream on which the data is to be sent.
|
||||
*
|
||||
* @param data The data to be sent on the stream.
|
||||
*
|
||||
* @param length The size of the data to be sent, in bytes.
|
||||
*
|
||||
* @param total_bytes_sent An optional output parameter that receives the
|
||||
* total number of bytes actually sent.
|
||||
*
|
||||
* @param error_handler The handler to be called when an error occurs. Copies
|
||||
* will be made of the handler as required. The equivalent function signature
|
||||
* of the handler must be:
|
||||
* @code template <typename Error>
|
||||
* void error_handler(
|
||||
* const Error& error // Result of operation (the actual type is dependent on
|
||||
* // the underlying stream's send operation)
|
||||
* ); @endcode
|
||||
*
|
||||
* @returns The number of bytes sent on the last send, or 0 if end-of-file was
|
||||
* reached or the connection was closed cleanly.
|
||||
*/
|
||||
template <typename Stream, typename Error_Handler>
|
||||
size_t send_n(Stream& s, const void* data, size_t length,
|
||||
size_t* total_bytes_sent, Error_Handler error_handler)
|
||||
{
|
||||
int bytes_sent = 0;
|
||||
size_t total_sent = 0;
|
||||
while (total_sent < length)
|
||||
{
|
||||
bytes_sent = send(s, static_cast<const char*>(data) + total_sent,
|
||||
length - total_sent, error_handler);
|
||||
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;
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
|
Loading…
Reference in New Issue
Block a user