Add support for sequenced packet sockets (SOCK_SEQPACKET).

This commit is contained in:
Christopher Kohlhoff 2011-02-09 11:35:45 +11:00
parent 39b6482b6b
commit ed62d29a67
18 changed files with 1373 additions and 0 deletions

View File

@ -4,6 +4,7 @@ nobase_include_HEADERS = \
asio/basic_deadline_timer.hpp \
asio/basic_io_object.hpp \
asio/basic_raw_socket.hpp \
asio/basic_seq_packet_socket.hpp \
asio/basic_serial_port.hpp \
asio/basic_socket_acceptor.hpp \
asio/basic_socket.hpp \
@ -128,6 +129,7 @@ nobase_include_HEADERS = \
asio/detail/reactive_socket_connect_op.hpp \
asio/detail/reactive_socket_recvfrom_op.hpp \
asio/detail/reactive_socket_recv_op.hpp \
asio/detail/reactive_socket_recvmsg_op.hpp \
asio/detail/reactive_socket_send_op.hpp \
asio/detail/reactive_socket_sendto_op.hpp \
asio/detail/reactive_socket_service_base.hpp \
@ -188,6 +190,7 @@ nobase_include_HEADERS = \
asio/detail/win_iocp_serial_port_service.hpp \
asio/detail/win_iocp_socket_accept_op.hpp \
asio/detail/win_iocp_socket_recvfrom_op.hpp \
asio/detail/win_iocp_socket_recvmsg_op.hpp \
asio/detail/win_iocp_socket_recv_op.hpp \
asio/detail/win_iocp_socket_send_op.hpp \
asio/detail/win_iocp_socket_service_base.hpp \
@ -263,6 +266,7 @@ nobase_include_HEADERS = \
asio/read_at.hpp \
asio/read.hpp \
asio/read_until.hpp \
asio/seq_packet_socket_service.hpp \
asio/serial_port_base.hpp \
asio/serial_port.hpp \
asio/serial_port_service.hpp \

View File

@ -19,6 +19,7 @@
#include "asio/basic_deadline_timer.hpp"
#include "asio/basic_io_object.hpp"
#include "asio/basic_raw_socket.hpp"
#include "asio/basic_seq_packet_socket.hpp"
#include "asio/basic_serial_port.hpp"
#include "asio/basic_socket_acceptor.hpp"
#include "asio/basic_socket_iostream.hpp"
@ -76,6 +77,7 @@
#include "asio/read.hpp"
#include "asio/read_at.hpp"
#include "asio/read_until.hpp"
#include "asio/seq_packet_socket_service.hpp"
#include "asio/serial_port.hpp"
#include "asio/serial_port_base.hpp"
#include "asio/serial_port_service.hpp"

View File

@ -0,0 +1,471 @@
//
// basic_seq_packet_socket.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BASIC_SEQ_PACKET_SOCKET_HPP
#define ASIO_BASIC_SEQ_PACKET_SOCKET_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/config.hpp"
#include <cstddef>
#include "asio/basic_socket.hpp"
#include "asio/detail/handler_type_requirements.hpp"
#include "asio/detail/throw_error.hpp"
#include "asio/error.hpp"
#include "asio/seq_packet_socket_service.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
/// Provides sequenced packet socket functionality.
/**
* The basic_seq_packet_socket class template provides asynchronous and blocking
* sequenced packet socket functionality.
*
* @par Thread Safety
* @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe.
*/
template <typename Protocol,
typename SeqPacketSocketService = seq_packet_socket_service<Protocol> >
class basic_seq_packet_socket
: public basic_socket<Protocol, SeqPacketSocketService>
{
public:
/// (Deprecated: Use native_handle_type.) The native representation of a
/// socket.
typedef typename SeqPacketSocketService::native_handle_type native_type;
/// The native representation of a socket.
typedef typename SeqPacketSocketService::native_handle_type
native_handle_type;
/// The protocol type.
typedef Protocol protocol_type;
/// The endpoint type.
typedef typename Protocol::endpoint endpoint_type;
/// Construct a basic_seq_packet_socket without opening it.
/**
* This constructor creates a sequenced packet socket without opening it. The
* socket needs to be opened and then connected or accepted before data can
* be sent or received on it.
*
* @param io_service The io_service object that the sequenced packet socket
* will use to dispatch handlers for any asynchronous operations performed on
* the socket.
*/
explicit basic_seq_packet_socket(asio::io_service& io_service)
: basic_socket<Protocol, SeqPacketSocketService>(io_service)
{
}
/// Construct and open a basic_seq_packet_socket.
/**
* This constructor creates and opens a sequenced_packet socket. The socket
* needs to be connected or accepted before data can be sent or received on
* it.
*
* @param io_service The io_service object that the sequenced packet socket
* will use to dispatch handlers for any asynchronous operations performed on
* the socket.
*
* @param protocol An object specifying protocol parameters to be used.
*
* @throws asio::system_error Thrown on failure.
*/
basic_seq_packet_socket(asio::io_service& io_service,
const protocol_type& protocol)
: basic_socket<Protocol, SeqPacketSocketService>(io_service, protocol)
{
}
/// Construct a basic_seq_packet_socket, opening it and binding it to the
/// given local endpoint.
/**
* This constructor creates a sequenced packet socket and automatically opens
* it bound to the specified endpoint on the local machine. The protocol used
* is the protocol associated with the given endpoint.
*
* @param io_service The io_service object that the sequenced packet socket
* will use to dispatch handlers for any asynchronous operations performed on
* the socket.
*
* @param endpoint An endpoint on the local machine to which the sequenced
* packet socket will be bound.
*
* @throws asio::system_error Thrown on failure.
*/
basic_seq_packet_socket(asio::io_service& io_service,
const endpoint_type& endpoint)
: basic_socket<Protocol, SeqPacketSocketService>(io_service, endpoint)
{
}
/// Construct a basic_seq_packet_socket on an existing native socket.
/**
* This constructor creates a sequenced packet socket object to hold an
* existing native socket.
*
* @param io_service The io_service object that the sequenced packet socket
* will use to dispatch handlers for any asynchronous operations performed on
* the socket.
*
* @param protocol An object specifying protocol parameters to be used.
*
* @param native_socket The new underlying socket implementation.
*
* @throws asio::system_error Thrown on failure.
*/
basic_seq_packet_socket(asio::io_service& io_service,
const protocol_type& protocol, const native_handle_type& native_socket)
: basic_socket<Protocol, SeqPacketSocketService>(
io_service, protocol, native_socket)
{
}
/// Send some data on the socket.
/**
* This function is used to send data on the sequenced packet socket. The
* function call will block until the data has been sent successfully, or an
* until error occurs.
*
* @param buffers One or more data buffers to be sent on the socket.
*
* @param flags Flags specifying how the send call is to be made.
*
* @returns The number of bytes sent.
*
* @throws asio::system_error Thrown on failure.
*
* @par Example
* To send a single data buffer use the @ref buffer function as follows:
* @code
* socket.send(asio::buffer(data, size), 0);
* @endcode
* See the @ref buffer documentation for information on sending multiple
* buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename ConstBufferSequence>
std::size_t send(const ConstBufferSequence& buffers,
socket_base::message_flags flags)
{
asio::error_code ec;
std::size_t s = this->service.send(
this->implementation, buffers, flags, ec);
asio::detail::throw_error(ec);
return s;
}
/// Send some data on the socket.
/**
* This function is used to send data on the sequenced packet socket. The
* function call will block the data has been sent successfully, or an until
* error occurs.
*
* @param buffers One or more data buffers to be sent on the socket.
*
* @param flags Flags specifying how the send call is to be made.
*
* @param ec Set to indicate what error occurred, if any.
*
* @returns The number of bytes sent. Returns 0 if an error occurred.
*
* @note The send operation may not transmit all of the data to the peer.
* Consider using the @ref write function if you need to ensure that all data
* is written before the blocking operation completes.
*/
template <typename ConstBufferSequence>
std::size_t send(const ConstBufferSequence& buffers,
socket_base::message_flags flags, asio::error_code& ec)
{
return this->service.send(this->implementation, buffers, flags, ec);
}
/// Start an asynchronous send.
/**
* This function is used to asynchronously send data on the sequenced packet
* socket. The function call always returns immediately.
*
* @param buffers One or more data buffers to be sent on the socket. Although
* the buffers object may be copied as necessary, ownership of the underlying
* memory blocks is retained by the caller, which must guarantee that they
* remain valid until the handler is called.
*
* @param flags Flags specifying how the send call is to be made.
*
* @param handler The handler to be called when the send operation completes.
* Copies will be made of the handler as required. The function signature of
* the handler must be:
* @code void handler(
* const asio::error_code& error, // Result of operation.
* std::size_t bytes_transferred // Number of bytes sent.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_service::post().
*
* @par Example
* To send a single data buffer use the @ref buffer function as follows:
* @code
* socket.async_send(asio::buffer(data, size), 0, handler);
* @endcode
* See the @ref buffer documentation for information on sending multiple
* buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename ConstBufferSequence, typename WriteHandler>
void async_send(const ConstBufferSequence& buffers,
socket_base::message_flags flags, WriteHandler handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
this->service.async_send(this->implementation, buffers, flags,
ASIO_MOVE_CAST(WriteHandler)(handler));
}
/// Receive some data on the socket.
/**
* This function is used to receive data on the sequenced packet socket. The
* function call will block until data has been received successfully, or
* until an error occurs.
*
* @param buffers One or more buffers into which the data will be received.
*
* @param out_flags After the receive call completes, contains flags
* associated with the received data. For example, if the
* socket_base::message_end_of_record bit is set then the received data marks
* the end of a record.
*
* @returns The number of bytes received.
*
* @throws asio::system_error Thrown on failure. An error code of
* asio::error::eof indicates that the connection was closed by the
* peer.
*
* @par Example
* To receive into a single data buffer use the @ref buffer function as
* follows:
* @code
* socket.receive(asio::buffer(data, size), out_flags);
* @endcode
* See the @ref buffer documentation for information on receiving into
* multiple buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename MutableBufferSequence>
std::size_t receive(const MutableBufferSequence& buffers,
socket_base::message_flags& out_flags)
{
asio::error_code ec;
std::size_t s = this->service.receive(
this->implementation, buffers, 0, out_flags, ec);
asio::detail::throw_error(ec);
return s;
}
/// Receive some data on the socket.
/**
* This function is used to receive data on the sequenced packet socket. The
* function call will block until data has been received successfully, or
* until an error occurs.
*
* @param buffers One or more buffers into which the data will be received.
*
* @param in_flags Flags specifying how the receive call is to be made.
*
* @param out_flags After the receive call completes, contains flags
* associated with the received data. For example, if the
* socket_base::message_end_of_record bit is set then the received data marks
* the end of a record.
*
* @returns The number of bytes received.
*
* @throws asio::system_error Thrown on failure. An error code of
* asio::error::eof indicates that the connection was closed by the
* peer.
*
* @note The receive operation may not receive all of the requested number of
* bytes. Consider using the @ref read function if you need to ensure that the
* requested amount of data is read before the blocking operation completes.
*
* @par Example
* To receive into a single data buffer use the @ref buffer function as
* follows:
* @code
* socket.receive(asio::buffer(data, size), 0, out_flags);
* @endcode
* See the @ref buffer documentation for information on receiving into
* multiple buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename MutableBufferSequence>
std::size_t receive(const MutableBufferSequence& buffers,
socket_base::message_flags in_flags,
socket_base::message_flags& out_flags)
{
asio::error_code ec;
std::size_t s = this->service.receive(
this->implementation, buffers, in_flags, out_flags, ec);
asio::detail::throw_error(ec);
return s;
}
/// Receive some data on a connected socket.
/**
* This function is used to receive data on the sequenced packet socket. The
* function call will block until data has been received successfully, or
* until an error occurs.
*
* @param buffers One or more buffers into which the data will be received.
*
* @param in_flags Flags specifying how the receive call is to be made.
*
* @param out_flags After the receive call completes, contains flags
* associated with the received data. For example, if the
* socket_base::message_end_of_record bit is set then the received data marks
* the end of a record.
*
* @param ec Set to indicate what error occurred, if any.
*
* @returns The number of bytes received. Returns 0 if an error occurred.
*
* @note The receive operation may not receive all of the requested number of
* bytes. Consider using the @ref read function if you need to ensure that the
* requested amount of data is read before the blocking operation completes.
*/
template <typename MutableBufferSequence>
std::size_t receive(const MutableBufferSequence& buffers,
socket_base::message_flags in_flags,
socket_base::message_flags& out_flags, asio::error_code& ec)
{
return this->service.receive(this->implementation,
buffers, in_flags, out_flags, ec);
}
/// Start an asynchronous receive.
/**
* This function is used to asynchronously receive data from the sequenced
* packet socket. The function call always returns immediately.
*
* @param buffers One or more buffers into which the data will be received.
* Although the buffers object may be copied as necessary, ownership of the
* underlying memory blocks is retained by the caller, which must guarantee
* that they remain valid until the handler is called.
*
* @param out_flags Once the asynchronous operation completes, contains flags
* associated with the received data. For example, if the
* socket_base::message_end_of_record bit is set then the received data marks
* the end of a record. The caller must guarantee that the referenced
* variable remains valid until the handler is called.
*
* @param handler The handler to be called when the receive operation
* completes. Copies will be made of the handler as required. The function
* signature of the handler must be:
* @code void handler(
* const asio::error_code& error, // Result of operation.
* std::size_t bytes_transferred // Number of bytes received.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_service::post().
*
* @par Example
* To receive into a single data buffer use the @ref buffer function as
* follows:
* @code
* socket.async_receive(asio::buffer(data, size), out_flags, handler);
* @endcode
* See the @ref buffer documentation for information on receiving into
* multiple buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename MutableBufferSequence, typename ReadHandler>
void async_receive(const MutableBufferSequence& buffers,
socket_base::message_flags& out_flags, ReadHandler handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
this->service.async_receive(this->implementation, buffers,
0, out_flags, ASIO_MOVE_CAST(ReadHandler)(handler));
}
/// Start an asynchronous receive.
/**
* This function is used to asynchronously receive data from the sequenced
* data socket. The function call always returns immediately.
*
* @param buffers One or more buffers into which the data will be received.
* Although the buffers object may be copied as necessary, ownership of the
* underlying memory blocks is retained by the caller, which must guarantee
* that they remain valid until the handler is called.
*
* @param in_flags Flags specifying how the receive call is to be made.
*
* @param out_flags Once the asynchronous operation completes, contains flags
* associated with the received data. For example, if the
* socket_base::message_end_of_record bit is set then the received data marks
* the end of a record. The caller must guarantee that the referenced
* variable remains valid until the handler is called.
*
* @param handler The handler to be called when the receive operation
* completes. Copies will be made of the handler as required. The function
* signature of the handler must be:
* @code void handler(
* const asio::error_code& error, // Result of operation.
* std::size_t bytes_transferred // Number of bytes received.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
* asio::io_service::post().
*
* @par Example
* To receive into a single data buffer use the @ref buffer function as
* follows:
* @code
* socket.async_receive(
* asio::buffer(data, size),
* 0, out_flags, handler);
* @endcode
* See the @ref buffer documentation for information on receiving into
* multiple buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename MutableBufferSequence, typename ReadHandler>
void async_receive(const MutableBufferSequence& buffers,
socket_base::message_flags in_flags,
socket_base::message_flags& out_flags, ReadHandler handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
this->service.async_receive(this->implementation, buffers,
in_flags, out_flags, ASIO_MOVE_CAST(ReadHandler)(handler));
}
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BASIC_SEQ_PACKET_SOCKET_HPP

View File

@ -919,6 +919,116 @@ bool non_blocking_recvfrom(socket_type s,
#endif // defined(ASIO_HAS_IOCP)
int recvmsg(socket_type s, buf* bufs, size_t count,
int in_flags, int& out_flags, asio::error_code& ec)
{
clear_last_error();
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
out_flags = 0;
return socket_ops::recv(s, bufs, count, in_flags, ec);
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
msghdr msg = msghdr();
msg.msg_iov = bufs;
msg.msg_iovlen = count;
int result = error_wrapper(::recvmsg(s, &msg, in_flags), ec);
if (result >= 0)
{
ec = asio::error_code();
out_flags = msg.msg_flags;
}
else
out_flags = 0;
return result;
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
}
size_t sync_recvmsg(socket_type s, state_type state,
buf* bufs, size_t count, int in_flags, int& out_flags,
asio::error_code& ec)
{
if (s == invalid_socket)
{
ec = asio::error::bad_descriptor;
return 0;
}
// Read some data.
for (;;)
{
// Try to complete the operation without blocking.
int bytes = socket_ops::recvmsg(s, bufs, count, in_flags, out_flags, ec);
// Check if operation succeeded.
if (bytes >= 0)
return bytes;
// Operation failed.
if ((state & user_set_non_blocking)
|| (ec != asio::error::would_block
&& ec != asio::error::try_again))
return 0;
// Wait for socket to become ready.
if (socket_ops::poll_read(s, ec) < 0)
return 0;
}
}
#if defined(ASIO_HAS_IOCP)
void complete_iocp_recvmsg(
const weak_cancel_token_type& cancel_token,
asio::error_code& ec)
{
// Map non-portable errors to their portable counterparts.
if (ec.value() == ERROR_NETNAME_DELETED)
{
if (cancel_token.expired())
ec = asio::error::operation_aborted;
else
ec = asio::error::connection_reset;
}
else if (ec.value() == ERROR_PORT_UNREACHABLE)
{
ec = asio::error::connection_refused;
}
}
#else // defined(ASIO_HAS_IOCP)
bool non_blocking_recvmsg(socket_type s,
buf* bufs, size_t count, int in_flags, int& out_flags,
asio::error_code& ec, size_t& bytes_transferred)
{
for (;;)
{
// Read some data.
int bytes = socket_ops::recvmsg(s, bufs, count, in_flags, out_flags, ec);
// Retry operation if interrupted by signal.
if (ec == asio::error::interrupted)
continue;
// Check if we need to run the operation again.
if (ec == asio::error::would_block
|| ec == asio::error::try_again)
return false;
// Operation is complete.
if (bytes >= 0)
{
ec = asio::error_code();
bytes_transferred = bytes;
}
else
bytes_transferred = 0;
return true;
}
}
#endif // defined(ASIO_HAS_IOCP)
int send(socket_type s, const buf* bufs, size_t count, int flags,
asio::error_code& ec)
{

View File

@ -0,0 +1,120 @@
//
// detail/reactive_socket_recvmsg_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_HPP
#define ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/config.hpp"
#include <boost/utility/addressof.hpp>
#include "asio/detail/bind_handler.hpp"
#include "asio/detail/buffer_sequence_adapter.hpp"
#include "asio/detail/fenced_block.hpp"
#include "asio/detail/reactor_op.hpp"
#include "asio/detail/socket_ops.hpp"
#include "asio/socket_base.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
template <typename MutableBufferSequence>
class reactive_socket_recvmsg_op_base : public reactor_op
{
public:
reactive_socket_recvmsg_op_base(socket_type socket,
const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
socket_base::message_flags& out_flags, func_type complete_func)
: reactor_op(&reactive_socket_recvmsg_op_base::do_perform, complete_func),
socket_(socket),
buffers_(buffers),
in_flags_(in_flags),
out_flags_(out_flags)
{
}
static bool do_perform(reactor_op* base)
{
reactive_socket_recvmsg_op_base* o(
static_cast<reactive_socket_recvmsg_op_base*>(base));
buffer_sequence_adapter<asio::mutable_buffer,
MutableBufferSequence> bufs(o->buffers_);
return socket_ops::non_blocking_recvmsg(o->socket_,
bufs.buffers(), bufs.count(),
o->in_flags_, o->out_flags_,
o->ec_, o->bytes_transferred_);
}
private:
socket_type socket_;
MutableBufferSequence buffers_;
socket_base::message_flags in_flags_;
socket_base::message_flags& out_flags_;
};
template <typename MutableBufferSequence, typename Handler>
class reactive_socket_recvmsg_op :
public reactive_socket_recvmsg_op_base<MutableBufferSequence>
{
public:
ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvmsg_op);
reactive_socket_recvmsg_op(socket_type socket,
const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
socket_base::message_flags& out_flags, Handler& handler)
: reactive_socket_recvmsg_op_base<MutableBufferSequence>(socket, buffers,
in_flags, out_flags, &reactive_socket_recvmsg_op::do_complete),
handler_(ASIO_MOVE_CAST(Handler)(handler))
{
}
static void do_complete(io_service_impl* owner, operation* base,
asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
{
// Take ownership of the handler object.
reactive_socket_recvmsg_op* o(
static_cast<reactive_socket_recvmsg_op*>(base));
ptr p = { boost::addressof(o->handler_), o, o };
// Make a copy of the handler so that the memory can be deallocated before
// the upcall is made. Even if we're not about to make an upcall, a
// sub-object of the handler may be the true owner of the memory associated
// with the handler. Consequently, a local copy of the handler is required
// to ensure that any owning sub-object remains valid until after we have
// deallocated the memory here.
detail::binder2<Handler, asio::error_code, std::size_t>
handler(o->handler_, o->ec_, o->bytes_transferred_);
p.h = boost::addressof(handler.handler_);
p.reset();
// Make the upcall if required.
if (owner)
{
asio::detail::fenced_block b;
asio_handler_invoke_helpers::invoke(handler, handler.handler_);
}
}
private:
Handler handler_;
};
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_HPP

View File

@ -27,6 +27,7 @@
#include "asio/detail/buffer_sequence_adapter.hpp"
#include "asio/detail/reactive_null_buffers_op.hpp"
#include "asio/detail/reactive_socket_recv_op.hpp"
#include "asio/detail/reactive_socket_recvmsg_op.hpp"
#include "asio/detail/reactive_socket_send_op.hpp"
#include "asio/detail/reactor.hpp"
#include "asio/detail/reactor_op.hpp"
@ -285,6 +286,81 @@ public:
p.v = p.p = 0;
}
// Receive some data with associated flags. Returns the number of bytes
// received.
template <typename MutableBufferSequence>
size_t receive_with_flags(base_implementation_type& impl,
const MutableBufferSequence& buffers,
socket_base::message_flags in_flags,
socket_base::message_flags& out_flags, asio::error_code& ec)
{
buffer_sequence_adapter<asio::mutable_buffer,
MutableBufferSequence> bufs(buffers);
return socket_ops::sync_recvmsg(impl.socket_, impl.state_,
bufs.buffers(), bufs.count(), in_flags, out_flags, ec);
}
// Wait until data can be received without blocking.
size_t receive_with_flags(base_implementation_type& impl,
const null_buffers&, socket_base::message_flags,
socket_base::message_flags& out_flags, asio::error_code& ec)
{
// Wait for socket to become ready.
socket_ops::poll_read(impl.socket_, ec);
// Clear out_flags, since we cannot give it any other sensible value when
// performing a null_buffers operation.
out_flags = 0;
return 0;
}
// Start an asynchronous receive. The buffer for the data being received
// must be valid for the lifetime of the asynchronous operation.
template <typename MutableBufferSequence, typename Handler>
void async_receive_with_flags(base_implementation_type& impl,
const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
socket_base::message_flags& out_flags, Handler& handler)
{
// Allocate and construct an operation to wrap the handler.
typedef reactive_socket_recvmsg_op<MutableBufferSequence, Handler> op;
typename op::ptr p = { boost::addressof(handler),
asio_handler_alloc_helpers::allocate(
sizeof(op), handler), 0 };
p.p = new (p.v) op(impl.socket_, buffers, in_flags, out_flags, handler);
start_op(impl,
(in_flags & socket_base::message_out_of_band)
? reactor::except_op : reactor::read_op,
p.p, (in_flags & socket_base::message_out_of_band) == 0, false);
p.v = p.p = 0;
}
// Wait until data can be received without blocking.
template <typename Handler>
void async_receive_with_flags(base_implementation_type& impl,
const null_buffers&, socket_base::message_flags in_flags,
socket_base::message_flags& out_flags, Handler& handler)
{
// Allocate and construct an operation to wrap the handler.
typedef reactive_null_buffers_op<Handler> op;
typename op::ptr p = { boost::addressof(handler),
asio_handler_alloc_helpers::allocate(
sizeof(op), handler), 0 };
p.p = new (p.v) op(handler);
// Clear out_flags, since we cannot give it any other sensible value when
// performing a null_buffers operation.
out_flags = 0;
start_op(impl,
(in_flags & socket_base::message_out_of_band)
? reactor::except_op : reactor::read_op,
p.p, false, false);
p.v = p.p = 0;
}
protected:
// Open a new socket implementation.
ASIO_DECL asio::error_code do_open(

View File

@ -168,6 +168,27 @@ ASIO_DECL bool non_blocking_recvfrom(socket_type s,
#endif // defined(ASIO_HAS_IOCP)
ASIO_DECL int recvmsg(socket_type s, buf* bufs, size_t count,
int in_flags, int& out_flags, asio::error_code& ec);
ASIO_DECL size_t sync_recvmsg(socket_type s, state_type state,
buf* bufs, size_t count, int in_flags, int& out_flags,
asio::error_code& ec);
#if defined(ASIO_HAS_IOCP)
ASIO_DECL void complete_iocp_recvmsg(
const weak_cancel_token_type& cancel_token,
asio::error_code& ec);
#else // defined(ASIO_HAS_IOCP)
ASIO_DECL bool non_blocking_recvmsg(socket_type s,
buf* bufs, size_t count, int in_flags, int& out_flags,
asio::error_code& ec, size_t& bytes_transferred);
#endif // defined(ASIO_HAS_IOCP)
ASIO_DECL int send(socket_type s, const buf* bufs,
size_t count, int flags, asio::error_code& ec);

View File

@ -112,6 +112,7 @@ const int shutdown_both = SD_BOTH;
const int message_peek = MSG_PEEK;
const int message_out_of_band = MSG_OOB;
const int message_do_not_route = MSG_DONTROUTE;
const int message_end_of_record = 0; // Not supported on Windows.
# if defined (_WIN32_WINNT)
const int max_iov_len = 64;
# else
@ -155,6 +156,7 @@ const int shutdown_both = SHUT_RDWR;
const int message_peek = MSG_PEEK;
const int message_out_of_band = MSG_OOB;
const int message_do_not_route = MSG_DONTROUTE;
const int message_end_of_record = MSG_EOR;
# if defined(IOV_MAX)
const int max_iov_len = IOV_MAX;
# else

View File

@ -0,0 +1,109 @@
//
// detail/win_iocp_socket_recvmsg_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_WIN_IOCP_SOCKET_RECVMSG_OP_HPP
#define ASIO_DETAIL_WIN_IOCP_SOCKET_RECVMSG_OP_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/config.hpp"
#if defined(ASIO_HAS_IOCP)
#include <boost/utility/addressof.hpp>
#include "asio/detail/bind_handler.hpp"
#include "asio/detail/buffer_sequence_adapter.hpp"
#include "asio/detail/fenced_block.hpp"
#include "asio/detail/handler_alloc_helpers.hpp"
#include "asio/detail/handler_invoke_helpers.hpp"
#include "asio/detail/operation.hpp"
#include "asio/detail/socket_ops.hpp"
#include "asio/error.hpp"
#include "asio/socket_base.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
template <typename MutableBufferSequence, typename Handler>
class win_iocp_socket_recvmsg_op : public operation
{
public:
ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_recvmsg_op);
win_iocp_socket_recvmsg_op(
socket_ops::weak_cancel_token_type cancel_token,
const MutableBufferSequence& buffers,
socket_base::message_flags& out_flags, Handler& handler)
: operation(&win_iocp_socket_recvmsg_op::do_complete),
cancel_token_(cancel_token),
buffers_(buffers),
out_flags_(out_flags),
handler_(ASIO_MOVE_CAST(Handler)(handler))
{
}
static void do_complete(io_service_impl* owner, operation* base,
asio::error_code ec, std::size_t bytes_transferred)
{
// Take ownership of the operation object.
win_iocp_socket_recvmsg_op* o(
static_cast<win_iocp_socket_recvmsg_op*>(base));
ptr p = { boost::addressof(o->handler_), o, o };
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
// Check whether buffers are still valid.
if (owner)
{
buffer_sequence_adapter<asio::mutable_buffer,
MutableBufferSequence>::validate(o->buffers_);
}
#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
socket_ops::complete_iocp_recvmsg(o->cancel_token_, ec);
o->out_flags_ = 0;
// Make a copy of the handler so that the memory can be deallocated before
// the upcall is made. Even if we're not about to make an upcall, a
// sub-object of the handler may be the true owner of the memory associated
// with the handler. Consequently, a local copy of the handler is required
// to ensure that any owning sub-object remains valid until after we have
// deallocated the memory here.
detail::binder2<Handler, asio::error_code, std::size_t>
handler(o->handler_, ec, bytes_transferred);
p.h = boost::addressof(handler.handler_);
p.reset();
// Make the upcall if required.
if (owner)
{
asio::detail::fenced_block b;
asio_handler_invoke_helpers::invoke(handler, handler.handler_);
}
}
private:
socket_ops::weak_cancel_token_type cancel_token_;
MutableBufferSequence buffers_;
socket_base::message_flags& out_flags_;
Handler handler_;
};
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // defined(ASIO_HAS_IOCP)
#endif // ASIO_DETAIL_WIN_IOCP_SOCKET_RECVMSG_OP_HPP

View File

@ -40,6 +40,7 @@
#include "asio/detail/win_iocp_null_buffers_op.hpp"
#include "asio/detail/win_iocp_socket_send_op.hpp"
#include "asio/detail/win_iocp_socket_recv_op.hpp"
#include "asio/detail/win_iocp_socket_recvmsg_op.hpp"
#include "asio/detail/push_options.hpp"
@ -301,6 +302,77 @@ public:
p.v = p.p = 0;
}
// Receive some data with associated flags. Returns the number of bytes
// received.
template <typename MutableBufferSequence>
size_t receive_with_flags(base_implementation_type& impl,
const MutableBufferSequence& buffers,
socket_base::message_flags in_flags,
socket_base::message_flags& out_flags, asio::error_code& ec)
{
buffer_sequence_adapter<asio::mutable_buffer,
MutableBufferSequence> bufs(buffers);
return socket_ops::sync_recvmsg(impl.socket_, impl.state_,
bufs.buffers(), bufs.count(), in_flags, out_flags, ec);
}
// Wait until data can be received without blocking.
size_t receive_with_flags(base_implementation_type& impl,
const null_buffers&, socket_base::message_flags,
socket_base::message_flags& out_flags, asio::error_code& ec)
{
// Wait for socket to become ready.
socket_ops::poll_read(impl.socket_, ec);
// Clear out_flags, since we cannot give it any other sensible value when
// performing a null_buffers operation.
out_flags = 0;
return 0;
}
// Start an asynchronous receive. The buffer for the data being received
// must be valid for the lifetime of the asynchronous operation.
template <typename MutableBufferSequence, typename Handler>
void async_receive_with_flags(base_implementation_type& impl,
const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
socket_base::message_flags& out_flags, Handler& handler)
{
// Allocate and construct an operation to wrap the handler.
typedef win_iocp_socket_recvmsg_op<MutableBufferSequence, Handler> op;
typename op::ptr p = { boost::addressof(handler),
asio_handler_alloc_helpers::allocate(
sizeof(op), handler), 0 };
p.p = new (p.v) op(impl.cancel_token_, buffers, out_flags, handler);
buffer_sequence_adapter<asio::mutable_buffer,
MutableBufferSequence> bufs(buffers);
start_receive_op(impl, bufs.buffers(), bufs.count(), in_flags, false, p.p);
p.v = p.p = 0;
}
// Wait until data can be received without blocking.
template <typename Handler>
void async_receive_with_flags(base_implementation_type& impl,
const null_buffers&, socket_base::message_flags in_flags,
socket_base::message_flags& out_flags, Handler& handler)
{
// Allocate and construct an operation to wrap the handler.
typedef win_iocp_null_buffers_op<Handler> op;
typename op::ptr p = { boost::addressof(handler),
asio_handler_alloc_helpers::allocate(
sizeof(op), handler), 0 };
p.p = new (p.v) op(impl.cancel_token_, handler);
// Reset out_flags since it can be given no sensible value at this time.
out_flags = 0;
start_null_buffers_receive_op(impl, in_flags, p.p);
p.v = p.p = 0;
}
// Helper function to restart an asynchronous accept operation.
ASIO_DECL void restart_accept_op(socket_type s,
socket_holder& new_socket, int family, int type, int protocol,

View File

@ -0,0 +1,317 @@
//
// seq_packet_socket_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_SEQ_PACKET_SOCKET_SERVICE_HPP
#define ASIO_SEQ_PACKET_SOCKET_SERVICE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/config.hpp"
#include <cstddef>
#include "asio/error.hpp"
#include "asio/io_service.hpp"
#if defined(ASIO_HAS_IOCP)
# include "asio/detail/win_iocp_socket_service.hpp"
#else
# include "asio/detail/reactive_socket_service.hpp"
#endif
#include "asio/detail/push_options.hpp"
namespace asio {
/// Default service implementation for a sequenced packet socket.
template <typename Protocol>
class seq_packet_socket_service
#if defined(GENERATING_DOCUMENTATION)
: public asio::io_service::service
#else
: public asio::detail::service_base<
seq_packet_socket_service<Protocol> >
#endif
{
public:
#if defined(GENERATING_DOCUMENTATION)
/// The unique service identifier.
static asio::io_service::id id;
#endif
/// The protocol type.
typedef Protocol protocol_type;
/// The endpoint type.
typedef typename Protocol::endpoint endpoint_type;
private:
// The type of the platform-specific implementation.
#if defined(ASIO_HAS_IOCP)
typedef detail::win_iocp_socket_service<Protocol> service_impl_type;
#else
typedef detail::reactive_socket_service<Protocol> service_impl_type;
#endif
public:
/// The type of a sequenced packet socket implementation.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined implementation_type;
#else
typedef typename service_impl_type::implementation_type implementation_type;
#endif
/// (Deprecated: Use native_handle_type.) The native socket type.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined native_type;
#else
typedef typename service_impl_type::native_handle_type native_type;
#endif
/// The native socket type.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined native_handle_type;
#else
typedef typename service_impl_type::native_handle_type native_handle_type;
#endif
/// Construct a new sequenced packet socket service for the specified
/// io_service.
explicit seq_packet_socket_service(asio::io_service& io_service)
: asio::detail::service_base<
seq_packet_socket_service<Protocol> >(io_service),
service_impl_(io_service)
{
}
/// Destroy all user-defined handler objects owned by the service.
void shutdown_service()
{
service_impl_.shutdown_service();
}
/// Construct a new sequenced packet socket implementation.
void construct(implementation_type& impl)
{
service_impl_.construct(impl);
}
/// Destroy a sequenced packet socket implementation.
void destroy(implementation_type& impl)
{
service_impl_.destroy(impl);
}
/// Open a sequenced packet socket.
asio::error_code open(implementation_type& impl,
const protocol_type& protocol, asio::error_code& ec)
{
if (protocol.type() == SOCK_SEQPACKET)
service_impl_.open(impl, protocol, ec);
else
ec = asio::error::invalid_argument;
return ec;
}
/// Assign an existing native socket to a sequenced packet socket.
asio::error_code assign(implementation_type& impl,
const protocol_type& protocol, const native_handle_type& native_socket,
asio::error_code& ec)
{
return service_impl_.assign(impl, protocol, native_socket, ec);
}
/// Determine whether the socket is open.
bool is_open(const implementation_type& impl) const
{
return service_impl_.is_open(impl);
}
/// Close a sequenced packet socket implementation.
asio::error_code close(implementation_type& impl,
asio::error_code& ec)
{
return service_impl_.close(impl, ec);
}
/// (Deprecated: Use native_handle().) Get the native socket implementation.
native_type native(implementation_type& impl)
{
return service_impl_.native_handle(impl);
}
/// Get the native socket implementation.
native_handle_type native_handle(implementation_type& impl)
{
return service_impl_.native_handle(impl);
}
/// Cancel all asynchronous operations associated with the socket.
asio::error_code cancel(implementation_type& impl,
asio::error_code& ec)
{
return service_impl_.cancel(impl, ec);
}
/// Determine whether the socket is at the out-of-band data mark.
bool at_mark(const implementation_type& impl,
asio::error_code& ec) const
{
return service_impl_.at_mark(impl, ec);
}
/// Determine the number of bytes available for reading.
std::size_t available(const implementation_type& impl,
asio::error_code& ec) const
{
return service_impl_.available(impl, ec);
}
/// Bind the sequenced packet socket to the specified local endpoint.
asio::error_code bind(implementation_type& impl,
const endpoint_type& endpoint, asio::error_code& ec)
{
return service_impl_.bind(impl, endpoint, ec);
}
/// Connect the sequenced packet socket to the specified endpoint.
asio::error_code connect(implementation_type& impl,
const endpoint_type& peer_endpoint, asio::error_code& ec)
{
return service_impl_.connect(impl, peer_endpoint, ec);
}
/// Start an asynchronous connect.
template <typename ConnectHandler>
void async_connect(implementation_type& impl,
const endpoint_type& peer_endpoint, ConnectHandler handler)
{
service_impl_.async_connect(impl, peer_endpoint, handler);
}
/// Set a socket option.
template <typename SettableSocketOption>
asio::error_code set_option(implementation_type& impl,
const SettableSocketOption& option, asio::error_code& ec)
{
return service_impl_.set_option(impl, option, ec);
}
/// Get a socket option.
template <typename GettableSocketOption>
asio::error_code get_option(const implementation_type& impl,
GettableSocketOption& option, asio::error_code& ec) const
{
return service_impl_.get_option(impl, option, ec);
}
/// Perform an IO control command on the socket.
template <typename IoControlCommand>
asio::error_code io_control(implementation_type& impl,
IoControlCommand& command, asio::error_code& ec)
{
return service_impl_.io_control(impl, command, ec);
}
/// Gets the non-blocking mode of the socket.
bool non_blocking(const implementation_type& impl) const
{
return service_impl_.non_blocking(impl);
}
/// Sets the non-blocking mode of the socket.
asio::error_code non_blocking(implementation_type& impl,
bool mode, asio::error_code& ec)
{
return service_impl_.non_blocking(impl, mode, ec);
}
/// Gets the non-blocking mode of the native socket implementation.
bool native_non_blocking(const implementation_type& impl) const
{
return service_impl_.native_non_blocking(impl);
}
/// Sets the non-blocking mode of the native socket implementation.
asio::error_code native_non_blocking(implementation_type& impl,
bool mode, asio::error_code& ec)
{
return service_impl_.native_non_blocking(impl, mode, ec);
}
/// Get the local endpoint.
endpoint_type local_endpoint(const implementation_type& impl,
asio::error_code& ec) const
{
return service_impl_.local_endpoint(impl, ec);
}
/// Get the remote endpoint.
endpoint_type remote_endpoint(const implementation_type& impl,
asio::error_code& ec) const
{
return service_impl_.remote_endpoint(impl, ec);
}
/// Disable sends or receives on the socket.
asio::error_code shutdown(implementation_type& impl,
socket_base::shutdown_type what, asio::error_code& ec)
{
return service_impl_.shutdown(impl, what, ec);
}
/// Send the given data to the peer.
template <typename ConstBufferSequence>
std::size_t send(implementation_type& impl,
const ConstBufferSequence& buffers,
socket_base::message_flags flags, asio::error_code& ec)
{
return service_impl_.send(impl, buffers, flags, ec);
}
/// Start an asynchronous send.
template <typename ConstBufferSequence, typename WriteHandler>
void async_send(implementation_type& impl,
const ConstBufferSequence& buffers,
socket_base::message_flags flags, WriteHandler handler)
{
service_impl_.async_send(impl, buffers, flags, handler);
}
/// Receive some data from the peer.
template <typename MutableBufferSequence>
std::size_t receive(implementation_type& impl,
const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
socket_base::message_flags& out_flags, asio::error_code& ec)
{
return service_impl_.receive_with_flags(impl,
buffers, in_flags, out_flags, ec);
}
/// Start an asynchronous receive.
template <typename MutableBufferSequence, typename ReadHandler>
void async_receive(implementation_type& impl,
const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
socket_base::message_flags& out_flags, ReadHandler handler)
{
service_impl_.async_receive_with_flags(impl,
buffers, in_flags, out_flags, handler);
}
private:
// The platform-specific implementation.
service_impl_type service_impl_;
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_SEQ_PACKET_SOCKET_SERVICE_HPP

View File

@ -62,6 +62,9 @@ public:
/// Specify that the data should not be subject to routing.
static const int message_do_not_route = implementation_defined;
/// Specifies that the data marks the end of a record.
static const int message_end_of_record = implementation_defined;
#else
BOOST_STATIC_CONSTANT(int,
message_peek = asio::detail::message_peek);
@ -69,6 +72,8 @@ public:
message_out_of_band = asio::detail::message_out_of_band);
BOOST_STATIC_CONSTANT(int,
message_do_not_route = asio::detail::message_do_not_route);
BOOST_STATIC_CONSTANT(int,
message_end_of_record = asio::detail::message_end_of_record);
#endif
/// Socket option to permit sending of broadcast messages.

View File

@ -14,6 +14,7 @@ check_PROGRAMS = \
tests/unit/basic_datagram_socket \
tests/unit/basic_deadline_timer \
tests/unit/basic_raw_socket \
tests/unit/basic_seq_packet_socket \
tests/unit/basic_serial_port \
tests/unit/basic_socket_acceptor \
tests/unit/basic_stream_socket \
@ -61,6 +62,7 @@ check_PROGRAMS = \
tests/unit/read \
tests/unit/read_at \
tests/unit/read_until \
tests/unit/seq_packet_socket_service \
tests/unit/serial_port \
tests/unit/serial_port_base \
tests/unit/serial_port_service \
@ -169,6 +171,7 @@ TESTS = \
tests/unit/basic_datagram_socket \
tests/unit/basic_deadline_timer \
tests/unit/basic_raw_socket \
tests/unit/basic_seq_packet_socket \
tests/unit/basic_serial_port \
tests/unit/basic_socket_acceptor \
tests/unit/basic_stream_socket \
@ -216,6 +219,7 @@ TESTS = \
tests/unit/read \
tests/unit/read_at \
tests/unit/read_until \
tests/unit/seq_packet_socket_service \
tests/unit/serial_port \
tests/unit/serial_port_base \
tests/unit/serial_port_service \
@ -272,6 +276,7 @@ tests_performance_server_SOURCES = tests/performance/server.cpp
tests_unit_basic_datagram_socket_SOURCES = tests/unit/basic_datagram_socket.cpp tests/unit/unit_test.cpp
tests_unit_basic_deadline_timer_SOURCES = tests/unit/basic_deadline_timer.cpp tests/unit/unit_test.cpp
tests_unit_basic_raw_socket_SOURCES = tests/unit/basic_raw_socket.cpp tests/unit/unit_test.cpp
tests_unit_basic_seq_packet_socket_SOURCES = tests/unit/basic_seq_packet_socket.cpp tests/unit/unit_test.cpp
tests_unit_basic_serial_port_SOURCES = tests/unit/basic_serial_port.cpp tests/unit/unit_test.cpp
tests_unit_basic_socket_acceptor_SOURCES = tests/unit/basic_socket_acceptor.cpp tests/unit/unit_test.cpp
tests_unit_basic_stream_socket_SOURCES = tests/unit/basic_stream_socket.cpp tests/unit/unit_test.cpp
@ -319,6 +324,7 @@ tests_unit_raw_socket_service_SOURCES = tests/unit/raw_socket_service.cpp tests/
tests_unit_read_SOURCES = tests/unit/read.cpp tests/unit/unit_test.cpp
tests_unit_read_at_SOURCES = tests/unit/read_at.cpp tests/unit/unit_test.cpp
tests_unit_read_until_SOURCES = tests/unit/read_until.cpp tests/unit/unit_test.cpp
tests_unit_seq_packet_socket_service_SOURCES = tests/unit/seq_packet_socket_service.cpp tests/unit/unit_test.cpp
tests_unit_serial_port_SOURCES = tests/unit/serial_port.cpp tests/unit/unit_test.cpp
tests_unit_serial_port_base_SOURCES = tests/unit/serial_port_base.cpp tests/unit/unit_test.cpp
tests_unit_serial_port_service_SOURCES = tests/unit/serial_port_service.cpp tests/unit/unit_test.cpp

View File

@ -17,6 +17,7 @@ UNIT_TEST_EXES = \
tests/unit/basic_datagram_socket.exe \
tests/unit/basic_deadline_timer.exe \
tests/unit/basic_raw_socket.exe \
tests/unit/basic_seq_packet_socket.exe \
tests/unit/basic_serial_port.exe \
tests/unit/basic_socket_acceptor.exe \
tests/unit/basic_stream_socket.exe \
@ -55,6 +56,7 @@ UNIT_TEST_EXES = \
tests/unit/read.exe \
tests/unit/read_at.exe \
tests/unit/read_until.exe \
tests/unit/seq_packet_socket_service.exe \
tests/unit/serial_port.exe \
tests/unit/serial_port_base.exe \
tests/unit/serial_port_service.exe \

View File

@ -82,6 +82,7 @@ UNIT_TEST_EXES = \
tests\unit\basic_datagram_socket.exe \
tests\unit\basic_deadline_timer.exe \
tests\unit\basic_raw_socket.exe \
tests\unit\basic_seq_packet_socket.exe \
tests\unit\basic_serial_port.exe \
tests\unit\basic_socket_acceptor.exe \
tests\unit\basic_stream_socket.exe \
@ -120,6 +121,7 @@ UNIT_TEST_EXES = \
tests\unit\read.exe \
tests\unit\read_at.exe \
tests\unit\read_until.exe \
tests\unit\seq_packet_socket_service.exe \
tests\unit\serial_port.exe \
tests\unit\serial_port_base.exe \
tests\unit\serial_port_service.exe \

View File

@ -10,6 +10,7 @@
basic_datagram_socket
basic_deadline_timer
basic_raw_socket
basic_seq_packet_socket
basic_serial_port
basic_socket_acceptor
basic_stream_socket
@ -33,6 +34,7 @@ raw_socket_service
read
read_at
read_until
seq_packet_socket_service
serial_port
serial_port_base
serial_port_service

View File

@ -0,0 +1,26 @@
//
// basic_seq_packet_socket.cpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Disable autolinking for unit tests.
#if !defined(BOOST_ALL_NO_LIB)
#define BOOST_ALL_NO_LIB 1
#endif // !defined(BOOST_ALL_NO_LIB)
// Test that header file is self-contained.
#include "asio/basic_seq_packet_socket.hpp"
#include "unit_test.hpp"
test_suite* init_unit_test_suite(int, char*[])
{
test_suite* test = BOOST_TEST_SUITE("basic_seq_packet_socket");
test->add(BOOST_TEST_CASE(&null_test));
return test;
}

View File

@ -0,0 +1,26 @@
//
// seq_packet_socket_service.cpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Disable autolinking for unit tests.
#if !defined(BOOST_ALL_NO_LIB)
#define BOOST_ALL_NO_LIB 1
#endif // !defined(BOOST_ALL_NO_LIB)
// Test that header file is self-contained.
#include "asio/seq_packet_socket_service.hpp"
#include "unit_test.hpp"
test_suite* init_unit_test_suite(int, char*[])
{
test_suite* test = BOOST_TEST_SUITE("seq_packet_socket_service");
test->add(BOOST_TEST_CASE(&null_test));
return test;
}